<html>
<head><meta charset="utf-8"><title>Opt-in guaranteed destructors · general · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/index.html">general</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html">Opt-in guaranteed destructors</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="211547326"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211547326" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211547326">(Sep 28 2020 at 20:39)</a>:</h4>
<p>I was chatting with embedded folks today, and we had this idea of adding an opt-in way to "defeat" the leakpocalypse. We would add the following to <code>core::mem</code>:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">pub</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="n">auto</span><span class="w"> </span><span class="k">trait</span><span class="w"> </span><span class="n">Leak</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>

<span class="k">pub</span><span class="w"> </span><span class="k">struct</span> <span class="nc">PhantomPlug</span><span class="p">;</span><span class="w"></span>

<span class="k">impl</span><span class="w"> </span><span class="o">!</span><span class="n">Leak</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">PhantomPlug</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
</code></pre></div>

<p><code>Leak</code> represents types that may be safely leaked. It is implemented for <em>all</em> Rust types, unless they contain a <code>PhantomPlug</code> (real name tbd). Since no currently written Rust type contains <code>PhantomPlug</code>, <em>everything</em> will remain leakable, which avoids breakage.</p>
<p>In addition to this, <code>T: Leak</code> would also have to become a default type parameter bound, similar to <code>T: Sized</code>. That way, every container on <a href="http://crates.io">crates.io</a> and liballoc that leaks stuff remains sound, even in the presence of types that must not be leaked. Containers that have been sufficiently reviewed and would like to give the user a hard guarantee that they won't leak their contents can then remove the bound via <code>T: ?Leak</code>. Due to how auto-traits work, if I then have a <code>Box&lt;T: !Leak&gt;</code>, the <code>Box</code> also stops implementing <code>Leak</code>, so I feel like this <em>should</em> impose the right requirement at all times. <code>mem::forget</code> and <code>Rc</code> as well as <code>Arc</code> would not be able to lift the implicit <code>Leak</code> bound, because they <em>can</em> be used to leak data.</p>
<p>Types that perform background I/O into a borrowed buffer would then add a <code>PhantomPlug</code> field, and could safely cancel or block on said I/O in their <code>Drop</code> implementation.</p>
<p>Now this is clearly far too simple to be correct and sufficient, right? Can anyone tell me where this idea falls apart?</p>



<a name="211547717"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211547717" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211547717">(Sep 28 2020 at 20:43)</a>:</h4>
<p>At the very least, current rough consensus as I interpret it in lang team is that another "?Sized" like trait is pretty high cost, and I think leak is unlikely to be seen as sufficiently interesting to warrant the cost</p>



<a name="211547758"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211547758" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211547758">(Sep 28 2020 at 20:43)</a>:</h4>
<p>To give a bit of motivation as to why we want to fix this:</p>
<p>On embedded systems, doing the same thing as ringbahn does (heap-allocating an owned backing buffer) would, as far as I understand, result in <em>doubling</em> memory usage of DMA buffers, which is not an acceptable trade-off there. The alternative would be to make almost every DMA API <code>unsafe</code>, which is also not appealing, and with async/await, that would be the <em>only</em> API, so that wouldn't be very good.</p>
<p>Such APIs could work fine with <code>&amp;'static mut</code> buffers, but those have move semantics and need to be pre-allocated statically (or leaked from the heap – and heap allocations are still unstable, and are generally undesirable; and if we could do this we might as well do what ringbahn does).</p>



<a name="211547995"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211547995" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211547995">(Sep 28 2020 at 20:45)</a>:</h4>
<p><span class="user-mention" data-user-id="116122">@simulacrum</span> Ah, I see. That's understandable, <code>#[no_std]</code> async/await is still fairly new, and I think we (embedded WG) haven't really been doing a good job at communicating with the lang team.</p>



<a name="211548108"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211548108" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211548108">(Sep 28 2020 at 20:46)</a>:</h4>
<p>Pretty unfortunate though, I don't really see us building usable DMA APIs without something like this...</p>



<a name="211548182"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211548182" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211548182">(Sep 28 2020 at 20:47)</a>:</h4>
<p>(for more details see recentish comments on unsized types rfcs)</p>



<a name="211548228"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211548228" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211548228">(Sep 28 2020 at 20:47)</a>:</h4>
<p>"Introduce Pointee and DynSized"?</p>



<a name="211548266"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211548266" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211548266">(Sep 28 2020 at 20:48)</a>:</h4>
<p>I think so, not sure, let me track it down</p>



<a name="211548378"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211548378" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211548378">(Sep 28 2020 at 20:48)</a>:</h4>
<p><a href="https://github.com/rust-lang/rfcs/pull/2984#issuecomment-694843100">https://github.com/rust-lang/rfcs/pull/2984#issuecomment-694843100</a></p>



<a name="211548505"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211548505" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211548505">(Sep 28 2020 at 20:50)</a>:</h4>
<p>I think Leak has a somewhat stronger motivation, but I don't think "strong enough"</p>



<a name="211548672"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211548672" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211548672">(Sep 28 2020 at 20:51)</a>:</h4>
<p>The problem comes down to imposing the cost of thinking about it on everyone. I'd be interested to hear how languages like C or C++, Zig(?) etc solve this - my guess is the answer is external whole program analysis of some kind with manual annotations?</p>



<a name="211548846"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211548846" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211548846">(Sep 28 2020 at 20:52)</a>:</h4>
<p>Or the language <em>doesn't</em> solve it, requiring the programmer to deal.</p>



<a name="211549105"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211549105" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211549105">(Sep 28 2020 at 20:54)</a>:</h4>
<p>C and C++ don't solve the problem, you get the usual headache of having to manually ensure all buffers live long enough, complicated by the fact that there is now an arbitrary number of read/write accesses going on in the background via DMA.</p>



<a name="211549279"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211549279" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Goat <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211549279">(Sep 28 2020 at 20:56)</a>:</h4>
<p>If I understand correctly, the original motivation was that <code>static</code>, <code>Rc</code> and <code>ManuallyDrop</code> (and thus also <code>MaybeUninit</code>) can let you avoid dropping safely, without <code>mem::forget</code>.</p>
<p>The latter two would soundly work with this thanks to their <code>Leak</code> bound, while <code>static</code>s and <code>Rc</code> could have this solved in a different way: specify that <code>!Leak</code> types <em>might actually not get dropped after all</em>, but the imaginary <code>mem::forget</code> there would happen <em>after</em> the <code>'static</code> lifetime.</p>



<a name="211549644"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211549644" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211549644">(Sep 28 2020 at 20:59)</a>:</h4>
<p>The problem is that <code>forget</code> makes any external buffer borrowed by the forgotten object accessible to the program again (the borrow's lifetime ends), but the destructor that would stop the I/O is not run before that happens. Are you proposing to change how <code>mem::forget</code> and <code>Rc</code> interact with the borrow checker?</p>



<a name="211549738"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211549738" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211549738">(Sep 28 2020 at 21:00)</a>:</h4>
<p><code>static</code> is not an issue by the way, it can't borrow any non-<code>'static</code> data</p>



<a name="211550739"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211550739" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211550739">(Sep 28 2020 at 21:08)</a>:</h4>
<p><span class="user-mention" data-user-id="323980">@Goat</span> ^</p>



<a name="211551081"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211551081" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211551081">(Sep 28 2020 at 21:11)</a>:</h4>
<p>Circling back to the proposal: I agree that adding another implicit bound would come at a cost, but what RFC 2984 proposes affects the often misunderstood <code>Sized</code> trait itself, which may bleed into diagnostics etc. and so make sizedness of types even harder to understand.</p>
<p>The <code>T: ?Leak</code> bound <em>would</em> show up in <code>std::collections</code> once they have been reviewed accordingly, but errors due to a missing <code>Leak</code> bound would only show up once the trait has been adopted by the ecosystem (so a while after stabilization).</p>



<a name="211551529"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211551529" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211551529">(Sep 28 2020 at 21:15)</a>:</h4>
<p>I think the problem is that too, but it's even just the cost of "every library defining a struct gets asked to add T: ?Leak" basically, right?</p>



<a name="211551652"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211551652" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211551652">(Sep 28 2020 at 21:17)</a>:</h4>
<p>Yeah, I can see that as a problem. Almost every type <em>can</em> add a <code>T: ?Leak</code> bound, after all, and if there's some fundamental io-uring type that doesn't implement <code>Leak</code> then that might bleed into large parts of the async ecosystem.</p>



<a name="211551729"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211551729" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211551729">(Sep 28 2020 at 21:18)</a>:</h4>
<p>This is less of a problem in embedded because things are much much smaller there, and I don't expect people to often do more than just <code>.await</code> the transaction immediately, so only the executor would have to cope with <code>!Leak</code> types.</p>



<a name="211552445"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211552445" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211552445">(Sep 28 2020 at 21:25)</a>:</h4>
<p>OTOH there isn't much to do with such an io-uring future other than <code>.await</code>ing it and using it with the <code>futures</code> combinators and possibly <code>std::collections</code>, so maybe the impact is fairly limited.</p>



<a name="211552491"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211552491" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211552491">(Sep 28 2020 at 21:26)</a>:</h4>
<p>Hmm, now one question is how this would interact with trait objects. You'd often have <code>Box&lt;dyn Future&gt;</code> after all.</p>



<a name="211780089"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211780089" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211780089">(Sep 30 2020 at 15:45)</a>:</h4>
<p>I think the other place the "cost of another implicit-bound auto trait is too high" conversation came up was with <code>?Move</code> for futures, but that's how we got <code>Pin</code> instead.</p>



<a name="211780860"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211780860" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Goat <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211780860">(Sep 30 2020 at 15:50)</a>:</h4>
<p>I also heard something about how <code>Pin</code> allows you to get guaranteed destructors as well, but I never got to fully understand how that'd work</p>



<a name="211781385"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211781385" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211781385">(Sep 30 2020 at 15:54)</a>:</h4>
<p><a href="https://doc.rust-lang.org/std/pin/index.html#drop-guarantee">https://doc.rust-lang.org/std/pin/index.html#drop-guarantee</a></p>
<blockquote>
<p>Notice that this guarantee does <em>not</em> mean that memory does not leak! It is still<br>
completely okay not ever to call <code>drop</code> on a pinned element (e.g., you can still<br>
call <code>mem::forget</code> on a <code>Pin&lt;Box&lt;T&gt;&gt;</code>). In the example of the doubly-linked<br>
list, that element would just stay in the list. However you may not free or reuse the storage<br>
<em>without calling <code>drop</code></em>.</p>
</blockquote>



<a name="211807393"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211807393" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211807393">(Sep 30 2020 at 19:19)</a>:</h4>
<blockquote>
<p>I also heard something about how Pin allows you to get guaranteed destructors as well, but I never got to fully understand how that'd work</p>
</blockquote>
<p>It boils down to the unsafe contact of <code>Pin::new_unchecked</code> being leaky/impure. I.e. it's correctness does not only depend on the value you pass to <code>new_unchecked</code> but also on how the value this value dereferences to is used after <code>Pin</code> is <del>dropped</del> out of scope (potentially leaked). </p>
<p>The most simple case is that you guaranteed that it's <em>not</em>  used in any place after the usage in <code>Pin</code>. Which is very similar to why embedded wants a guaranteed drop for DMA.</p>



<a name="211807844"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211807844" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211807844">(Sep 30 2020 at 19:23)</a>:</h4>
<p>Since I forgot to state it alongside my earlier quote, my reading is that <code>Pin</code> does <strong>not</strong> guarantee that the destructor is run.</p>



<a name="211807871"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211807871" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211807871">(Sep 30 2020 at 19:23)</a>:</h4>
<p>Yes, it doesn't.</p>



<a name="211808669"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211808669" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211808669">(Sep 30 2020 at 19:31)</a>:</h4>
<p>It just guarantee that you don't reuse that memory <em>until</em> drop is run.</p>
<p>So if you don't drop you can't reuse the memory.</p>
<p>Which is where the "leakyness"/impurity of <code>Pin::new_unchecked</code> comes in, it makes you guarantees about the usage of the value you pinned through some pointer. </p>
<p>And sure if you can guarantee the value is properly dropped you don't need to uphold any guarantees for it anymore and can reuse it's memory slot.</p>



<a name="211809479"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211809479" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211809479">(Sep 30 2020 at 19:37)</a>:</h4>
<hr>
<p>As far as I understand the thing embedded/DMA needs is the guarantee that the memory/buffer is not reused until the DMA operation started on it did finish or was successfully canceled (which might not happen in a <code>Drop</code> of some kind of handler type representing the DMA operation).</p>



<a name="211810119"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211810119" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211810119">(Sep 30 2020 at 19:43)</a>:</h4>
<p>If that's the case and if I understand (the latter being less likely), then the fact that <code>Pin</code> really isn't _that_ special should be relevant. <code>Pin</code> is basically just a type-system marker to the programmer. It should be possible to create <code>MyPinLikeThing&lt;T&gt;</code> that has whatever desired semantics.</p>



<a name="211811273"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211811273" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211811273">(Sep 30 2020 at 19:52)</a>:</h4>
<p>Yes, but it is <em>very</em> hard to get right.</p>
<p>A lot of very clever people double and tipple checked <code>Pin</code> and we currently still have soundness holes in it (which currently probably can't be taken advantage of on stable).</p>
<p>Mainly the way it interacts with <code>CoerceUnsized</code> is not fully sound and the interaction it has with how <code>fundamental types</code> works is potentially also not fully sound (but you seem to need the <code>CoerceUnsized</code> "hole" to take advantage of it? probably?).</p>
<p>Furthermore the discussions around it doesn't give me any trust in that all or even most people involved do fully understand all implication derived from <code>Pin</code>'s unsafe contract and it's interaction with all other parts of rust (and that's not because of missing skill but of a lot of hidden complexity).</p>
<p>Lastly it would mean that any <code>DMA</code> setup would need to use some unsafe code to do something like <code>Pin:new_unchecked</code> but in a way which might likely in the constraints of embedded be harder to abstract over and IMHO <code>Pin::new_unchecked</code> is probably the hardest to get right unsafe rust function I have seen.</p>



<a name="211811449"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211811449" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211811449">(Sep 30 2020 at 19:53)</a>:</h4>
<p>I agree with all your points, but my main idea/thrust is that it can be prototyped outside of the standard library, like a lot of futures stuff was.</p>



<a name="211811589"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211811589" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211811589">(Sep 30 2020 at 19:54)</a>:</h4>
<p>The problem we're trying to solve is isomorphic to building an asynchronous interface to completion-based I/O APIs like io-uring and IOCP, so the same problems and potential solutions apply</p>



<a name="211811897"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211811897" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211811897">(Sep 30 2020 at 19:57)</a>:</h4>
<p>Sure, I also feel that with a stable <code>alloca</code>/<code>unsized types on stack</code> we might be able to have a <code>Pin</code> like API with proper safe abstractions around it for DMA.  </p>
<p><span class="user-mention" data-user-id="211727">@Jonas Schievink</span> : Is there any kind of blog, rust user/internal forum thread which has more details about what exactly the problems with DMA are? I have hardly any embedded experience so I might very likely missguess what exactly is needed <span aria-label="wink" class="emoji emoji-1f609" role="img" title="wink">:wink:</span> . EDIT: Wrote this before receiving/reading you last comment.</p>



<a name="211812614"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211812614" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211812614">(Sep 30 2020 at 20:02)</a>:</h4>
<p>There are some fundamental shortcomings in the usual approaches taken for such an API, namely:</p>
<ul>
<li>An API may be built that uses <code>&amp;'static mut</code> buffers only, which have move semantics. The problem is that the DMA API then takes ownership of the buffer, and <em>somehow</em> needs to give it back to the caller, which results in awkward APIs, and the limitation to <code>'static</code> means that no on-stack buffers can be used.</li>
<li>A blocking API can be used. The library code has full control over the entire duration of the transfer and works fine with on-stack buffers. Drawback: <em>Nothing</em> else can be done while the transfer is in progress, which is too limiting for embedded apps (with a framework like <a href="https://rtic.rs/">RTIC</a> this operation can be preempted and other code can run, but this is still fairly limiting).</li>
<li>An owned intermediate buffer can be used for all asynchronous I/O. I believe this is the approach that ringbahn takes, and it solves the problem by leaking the memory that is being accessed when the transfer type is leaked. This is impractical on embedded due to the increased (potentially doubled) memory usage.</li>
</ul>
<p>These are all approaches I am aware of. There might be more that I haven't seen yet.</p>



<a name="211813088"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211813088" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211813088">(Sep 30 2020 at 20:06)</a>:</h4>
<p>Fundamentally, if you have an API like this:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">async</span><span class="w"> </span><span class="k">fn</span> <span class="nf">transfer</span><span class="p">(</span><span class="n">dest</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="p">[</span><span class="kt">u8</span><span class="p">])</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="c1">// ...</span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>

<p>Callers are always free to drop or leak the <code>impl Future</code> after creating and polling it. This ends the borrow of <code>dest</code> and makes it accessible to the original owner again.</p>
<p>I don't see any way of avoiding this other than language-level support for types whose destructors must run before they give back their loan on the borrowed data.</p>



<a name="211813690"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211813690" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211813690">(Sep 30 2020 at 20:11)</a>:</h4>
<blockquote>
<p>which have move semantics.</p>
</blockquote>
<p>You mentioned that earlier, but _everything_ has move semantics, so I'm lost.</p>



<a name="211813918"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211813918" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211813918">(Sep 30 2020 at 20:13)</a>:</h4>
<p>And what's the ideal goal / API?</p>



<a name="211813933"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211813933" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211813933">(Sep 30 2020 at 20:14)</a>:</h4>
<p><code>&amp;mut [u8]</code> doesn't due to reborrows, but <code>&amp;'static [u8]</code> always moves ownership of the reference</p>



<a name="211814583"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211814583" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211814583">(Sep 30 2020 at 20:18)</a>:</h4>
<blockquote>
<p>Callers are always free to drop or leak the impl Future after creating and polling it. This ends the borrow of dest and makes it accessible to the original owner again.</p>
</blockquote>
<p>Is the problem that if they drop the future that the DMA engine can still write to that memory? And some other Rust code might have since assumed it was immutable?</p>



<a name="211814680"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211814680" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211814680">(Sep 30 2020 at 20:19)</a>:</h4>
<p>If so, feels a lot like shared ownership / internal mutability.</p>



<a name="211814821"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211814821" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211814821">(Sep 30 2020 at 20:20)</a>:</h4>
<p>Do we have any stack-only <code>Rc</code>?</p>



<a name="211814831"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211814831" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211814831">(Sep 30 2020 at 20:20)</a>:</h4>
<p>Yes, the transfer just runs in the background and needs to be explicitly stopped or blocked on</p>



<a name="211814886"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211814886" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211814886">(Sep 30 2020 at 20:20)</a>:</h4>
<p>Why do you need <code>Rc</code>? Sounds more like something on top of <code>UnsafeCell</code> might help, but I don't immediately see how</p>



<a name="211814976"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211814976" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211814976">(Sep 30 2020 at 20:21)</a>:</h4>
<p>I'm thinking <code>Rc</code> mostly because I'd want to model it as "owned by me / owned by DMA"</p>



<a name="211815005"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211815005" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211815005">(Sep 30 2020 at 20:21)</a>:</h4>
<p>on the first <code>poll</code>, you mark it as owned by DMA</p>



<a name="211815018"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211815018" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211815018">(Sep 30 2020 at 20:21)</a>:</h4>
<p>and it it already was, you panic.</p>



<a name="211815088"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211815088" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211815088">(Sep 30 2020 at 20:22)</a>:</h4>
<p>You could already do that by moving an owned buffer into and out of the transfer</p>



<a name="211815132"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211815132" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211815132">(Sep 30 2020 at 20:22)</a>:</h4>
<p>Which, I guess, is the least awful API we can build right now, but still won't work with on-stack buffers at all</p>



<a name="211815149"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211815149" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211815149">(Sep 30 2020 at 20:23)</a>:</h4>
<p>This actually you can use Pin for:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">async</span><span class="w"> </span><span class="k">fn</span> <span class="nf">transfer</span><span class="p">(</span><span class="n">dest</span>: <span class="nc">Pin</span><span class="o">&lt;&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">MustFree</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="k">struct</span> <span class="nc">MustFree</span><span class="p">(</span><span class="kt">bool</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="kt">u8</span><span class="p">]);</span><span class="w"></span>
<span class="k">impl</span><span class="w"> </span><span class="nb">Drop</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">MustFree</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">drop</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">abort</span><span class="p">();</span><span class="w"> </span><span class="cm">/* Not been freed */</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="211815155"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211815155" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211815155">(Sep 30 2020 at 20:23)</a>:</h4>
<p>but the moving back out is the ugly part of that, right?</p>



<a name="211815236"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211815236" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211815236">(Sep 30 2020 at 20:23)</a>:</h4>
<p><span class="user-mention" data-user-id="229913">@HeroicKatora</span> I thought you were still allowed to not call <code>Drop</code> on that?</p>



<a name="211815307"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211815307" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211815307">(Sep 30 2020 at 20:24)</a>:</h4>
<p>Or would you have to, before the <code>&amp;mut MustFree</code> borrow ends?</p>



<a name="211815355"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211815355" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211815355">(Sep 30 2020 at 20:24)</a>:</h4>
<p><span class="user-mention silent" data-user-id="116155">Jake Goulding</span> <a href="#narrow/stream/122651-general/topic/Opt-in.20guaranteed.20destructors/near/211815155">said</a>:</p>
<blockquote>
<p>but the moving back out is the ugly part of that, right?</p>
</blockquote>
<p>The worst part is probably that it doesn't work with on-stack buffers</p>



<a name="211815394"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211815394" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211815394">(Sep 30 2020 at 20:25)</a>:</h4>
<p>I would be fine with a slightly awkward API if it meant that it works with on-stack buffers</p>



<a name="211815452"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211815452" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211815452">(Sep 30 2020 at 20:25)</a>:</h4>
<p>I was thinking something like</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="n">buf</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Thing</span>::<span class="n">new</span><span class="p">([</span><span class="mi">0</span><span class="k">u8</span><span class="p">;</span><span class="w"> </span><span class="mi">8</span><span class="p">]);</span><span class="w"></span>

<span class="k">async</span><span class="w"> </span><span class="k">fn</span> <span class="nf">transfer</span><span class="p">(</span><span class="n">dest</span>: <span class="kp">&amp;</span><span class="nc">Thing</span><span class="p">)</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
</code></pre></div>

<p>And then you flip the cell inside when the poll starts and check the cell when you want the data.</p>



<a name="211815520"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211815520" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211815520">(Sep 30 2020 at 20:26)</a>:</h4>
<p>so <code>buf</code> is on the stack</p>



<a name="211815782"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211815782" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211815782">(Sep 30 2020 at 20:28)</a>:</h4>
<p>You could still leak the future and deallocate <code>buf</code> without stopping the transfer though</p>



<a name="211815872"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211815872" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211815872">(Sep 30 2020 at 20:29)</a>:</h4>
<p>Ah, I didn't realize that stopping it was an important goal. I thought it was more about preventing the memory unsafety.</p>



<a name="211815954"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211815954" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211815954">(Sep 30 2020 at 20:29)</a>:</h4>
<p>It feels like if you leak a value and your system locks up, that's more of a "don't do that" issue, but I understand wanting to get the compiler to do as much as possible.</p>



<a name="211816019"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211816019" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211816019">(Sep 30 2020 at 20:30)</a>:</h4>
<p>The unsafety arises when you reuse the array's memory later and DMA writes to it ;)</p>



<a name="211816061"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211816061" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211816061">(Sep 30 2020 at 20:30)</a>:</h4>
<p>Took a while to check: If you don#t call drop on it, you must leak it</p>



<a name="211816184"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211816184" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211816184">(Sep 30 2020 at 20:31)</a>:</h4>
<p>Which is precisely as strong as you need. The caller can either leak the buffer, aka. move ownership to the DMA.<br>
Or they can choose to wait on getting it back and drop it, but then they can not leak it.</p>



<a name="211816329"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211816329" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211816329">(Sep 30 2020 at 20:33)</a>:</h4>
<p>Now I've lost myself: what does leaking a future do with the stack frames within the future? I know I'm not using the terminology correctly, but I can't figure out how best to phrase it.</p>



<a name="211817264"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211817264" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211817264">(Sep 30 2020 at 20:41)</a>:</h4>
<p>You can leak a future, as if leaving it just permanently pending. The 'stack frame' is just another struct, well it's more like an enum internally, so you'll also leak any of those resources. You don't want to do it but it would be sound. In this particular instance, the DMA could continue to write into the buffer without any real effect.</p>



<a name="211817591"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211817591" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211817591">(Sep 30 2020 at 20:43)</a>:</h4>
<p>Right, that's the thing I'm stuck on. So you leak a future but the DMA writes to the futures "stack frame". When would that be unsound in the first place?</p>



<a name="211817631"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211817631" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211817631">(Sep 30 2020 at 20:43)</a>:</h4>
<p>If you'd deallocate the frame and reuse the memory for something else.</p>



<a name="211817723"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211817723" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211817723">(Sep 30 2020 at 20:44)</a>:</h4>
<p>Then the other side of the DMA would continue to write but, oh no, it now overwrites some arbitrary other object's data.</p>



<a name="211817925"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211817925" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211817925">(Sep 30 2020 at 20:45)</a>:</h4>
<p>Now you've said deallocate though.</p>



<a name="211818138"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211818138" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211818138">(Sep 30 2020 at 20:46)</a>:</h4>
<p>This dilemma makes it impossible to have an unpinned guard that somehow waits on the DMA transfer in its Drop.<br>
If something isn't pinned, I can skip its drop impl by leaking it, and then immediately pretend the guard's lifetime has ended.<br>
Pinning makes this an xor choice: Either leak it and preserve the guard forever, OR drop the guard.</p>



<a name="211818211"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211818211" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211818211">(Sep 30 2020 at 20:47)</a>:</h4>
<p>Is it something like this?</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">async</span><span class="w"> </span><span class="k">fn</span> <span class="nf">example</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">buf</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="k">u8</span><span class="p">;</span><span class="w"> </span><span class="mi">8</span><span class="p">];</span><span class="w"></span>
<span class="w">    </span><span class="n">start_dma</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">buf</span><span class="p">).</span><span class="k">await</span><span class="p">;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">async</span><span class="w"> </span><span class="k">fn</span> <span class="nf">exercise</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">mem</span>::<span class="n">forget</span><span class="p">(</span><span class="n">example</span><span class="p">());</span><span class="w"></span>
<span class="w">    </span><span class="n">example</span><span class="p">().</span><span class="k">await</span><span class="p">;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="211818523"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211818523" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211818523">(Sep 30 2020 at 20:49)</a>:</h4>
<p>Ah, okay, so you would have to pin the buffer before starting the I/O, not the returned future before polling it?</p>



<a name="211818580"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211818580" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211818580">(Sep 30 2020 at 20:49)</a>:</h4>
<p>Pinning the buffer doesn't do anything.</p>



<a name="211818656"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211818656" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211818656">(Sep 30 2020 at 20:50)</a>:</h4>
<p>The buffer is <code>[u8]</code> which just has an empty drop</p>



<a name="211818714"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211818714" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211818714">(Sep 30 2020 at 20:50)</a>:</h4>
<p>You need to pin a _guard_ that _owns_ the buffer, and waits for completion in its drop.</p>



<a name="211818801"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211818801" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211818801">(Sep 30 2020 at 20:51)</a>:</h4>
<p>Owning can be a temporary <code>&amp;mut [u8]</code>, that's fine</p>



<a name="211819028"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211819028" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211819028">(Sep 30 2020 at 20:52)</a>:</h4>
<p>Yes</p>



<a name="211819118"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211819118" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211819118">(Sep 30 2020 at 20:53)</a>:</h4>
<p>That seems like it would lead to a hard to use API though, having to unsafely pin buffers before doing I/O</p>



<a name="211819241"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211819241" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211819241">(Sep 30 2020 at 20:54)</a>:</h4>
<p>You can pin on the stack.<br>
That's one very simple form of pinning that makes leaking impossible.</p>



<a name="211819278"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211819278" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211819278">(Sep 30 2020 at 20:54)</a>:</h4>
<p>i.e. <code>pin_mut!</code>?</p>



<a name="211825875"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211825875" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211825875">(Sep 30 2020 at 20:54)</a>:</h4>
<p>I believe that is what it's called in <code>pin-utils</code>, yes.</p>



<a name="211825927"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211825927" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211825927">(Sep 30 2020 at 20:55)</a>:</h4>
<p><a href="https://docs.rs/futures/0.3.5/futures/macro.pin_mut.html">and re-exported in futures</a></p>



<a name="211826094"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211826094" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211826094">(Sep 30 2020 at 20:56)</a>:</h4>
<p>I wish it just had proper language support though, it's correct but always feels sketchy to rely on shadowing.</p>



<a name="211826167"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211826167" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211826167">(Sep 30 2020 at 20:57)</a>:</h4>
<p>It's 100% sound though afaik, it's just a weird feeling</p>



<a name="211827234"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211827234" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Dario Nieuwenhuis <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211827234">(Sep 30 2020 at 21:06)</a>:</h4>
<blockquote>
<p>That's one very simple form of pinning that makes leaking impossible.</p>
</blockquote>
<p>nope, you can pin on the "stack" of an async fn and then leak its future</p>



<a name="211827798"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211827798" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211827798">(Sep 30 2020 at 21:11)</a>:</h4>
<p>FWIW I think moving pin_mut! into core/std is quite reasonable, it definitely feels like a foundation construct. I imagine someone could mostly just open a PR to that effect</p>



<a name="211829395"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211829395" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211829395">(Sep 30 2020 at 21:26)</a>:</h4>
<p>You need to pin <em>both</em> the guard (which implements drop) and the buffer!</p>
<ul>
<li>Pin guard =&gt; to make sure it's only used iff drop is called</li>
<li>Pin buffer =&gt; to make sure the buffer is not used until the guard's drop is called</li>
</ul>
<p>So you would have something like <code>struct DMABufffer { guard: Guard, buffer: [u8] }</code>  or  e.g. <code>struct DMABuffer&lt;'a&gt; { guard: Guard, buffer: Pin&lt;&amp;'a [u8]&gt;</code>.</p>
<p>Then a <code>Pin&lt;&amp;mut DMABuffer&gt;</code> would give you the right guarantees and doesn't exclude the chance to re-use the given memory.</p>
<p>But! How do we get the guarantee? =&gt; Through the <code>unsafe contract</code> of <code>Pin::new_unchecked</code>.</p>
<p>This means we on a saftey level we either guarantee to not never use the memory  of <code>DMABuffer</code> again or to guarantee that drop will be called on <code>DMABuffer</code>!</p>
<p>So the reason <code>Pin</code> works (for this) is because it's defined to only work if you already can guarantee it works...</p>
<p>The think is DMA is like another liftime-wise unbound thread  having a reference to the data.</p>
<p>Btw. I think I just realized that pinning any stack allocated future is technically braking the <code>Pin</code> unsafe-contract. It's just that because when we leak pin, drop the stack frame and reallocate the stack frame (defacto reusing memory) due to lifetimes we can't "poke" the leaked and not droped but mem-resued future anymore and as such can't exploit the contract breach. Uhm we might need to reformulate the unsafe-contract of <code>Pin</code>...</p>



<a name="211830352"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211830352" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211830352">(Sep 30 2020 at 21:35)</a>:</h4>
<hr>
<p>So I think for a API you needs:</p>
<ul>
<li>Something like the <code>DMABuffer</code> struct mentioned above but with another  <code>referenced: bool</code> field (or maybe <code>Cell&lt;bool&gt;</code> or similar)</li>
<li>EDIT: Due to the stack frame drop and reallocation issues mentioned above the buffer <em>must not</em> be stack allocated except if you (through some unsafe contract) guarantee that the stack-frame it's one never get dropped. </li>
<li>
<p>A fallible way to turn a <code>&amp;mut DMABuffer</code> into a <code>Pin&lt;&amp;mut DMABuffer&gt;</code> which sets the <code>referenced</code> boolean  to <code>true</code> and<br>
  fails if it already was set to true.</p>
</li>
<li>
<p>Methods taking <code>Pin&lt;&amp;mut DMABuffer&gt;</code></p>
</li>
</ul>
<p>With that you would guarantee to only handout a new <code>Pin&lt;&amp;mut DMABuffer&gt;</code> if the previous one was dropped and <code>Pin</code> would<br>
prevent any strange move/reborrow problems.</p>



<a name="211830649"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211830649" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211830649">(Sep 30 2020 at 21:38)</a>:</h4>
<p>The only two <em>big</em> drawback:</p>
<ul>
<li>
<p>With <code>Leak</code> you have the guarantee that <code>Drop</code> was called</p>
</li>
<li>
<p>With the API you don't, you just don't accidental re-use it but<br>
  what can you do if you run into it being locked. Either retry after<br>
  a moment or leak the memory forever or panic and restart. Non<br>
  of which is really nice tbh. EDIT: And no stack allocated buffers.</p>
</li>
</ul>



<a name="211830705"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211830705" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211830705">(Sep 30 2020 at 21:39)</a>:</h4>
<p>How would one construct a safe API like that ? The user can always safely mem::forget the future/pinned buffer and by the end of the scope the stack would be popped and DMA would write to another stack frame</p>



<a name="211830894"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211830894" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211830894">(Sep 30 2020 at 21:41)</a>:</h4>
<p>Let's say the user provides the buffer and pins it on the stack with <code>pin_mut</code>, passes the <code>Pin&lt;&amp;mut Buffer&gt;</code> to the <code>Transfer</code>, and then forgets the transfer and leaves the stack frame</p>



<a name="211830914"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211830914" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211830914">(Sep 30 2020 at 21:41)</a>:</h4>
<p><span aria-label="face palm" class="emoji emoji-1f926" role="img" title="face palm">:face_palm:</span> I forgot the most important bullet point. I will edit it.</p>



<a name="211837534"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211837534" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211837534">(Sep 30 2020 at 21:42)</a>:</h4>
<p>Is there something preventing it from just leaving the stack frame without calling Drop on the Transfer or anything for that matter ?</p>



<a name="211837683"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211837683" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211837683">(Sep 30 2020 at 21:43)</a>:</h4>
<p>Hmm, wait, maybe if you pin the transfer too with pin_mut</p>



<a name="211837960"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211837960" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211837960">(Sep 30 2020 at 21:46)</a>:</h4>
<p>As far as I know you can not make sure that the stack-frame the buffer is one is never dropped (besides putting it into a function which never exists outside of a hardware reset).</p>



<a name="211838016"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211838016" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211838016">(Sep 30 2020 at 21:47)</a>:</h4>
<p>I think that's possible using both pinned Buffer and pinned Transfer on the stack with pin_mut, but then you're back to move semantics, i.e. the user gives all itz access to the buffer to the Transfer and the transfer has to give it back</p>



<a name="211838171"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211838171" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211838171">(Sep 30 2020 at 21:48)</a>:</h4>
<p><code>pin_mut</code> shadows the original thing, so the drop will be called by the end of the scope, but I don't see how this is better than a <code>&amp;'static [u8]</code></p>



<a name="211838371"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211838371" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211838371">(Sep 30 2020 at 21:50)</a>:</h4>
<p>You would need to make sure that there is no longer any ongoing DMA when the function exist or the stack will be clobbered by DMA.</p>



<a name="211838454"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211838454" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211838454">(Sep 30 2020 at 21:51)</a>:</h4>
<p>We can do that on the drop of the Transfer type, if we only start it after having a <code>Pin&lt;&amp;mut Transfer&gt;</code>, and the Transfer would need to be !Unpin of course</p>



<a name="211838562"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211838562" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211838562">(Sep 30 2020 at 21:52)</a>:</h4>
<p>But we also need move semantics on the buffer, otherwise we could reuse the buffer (in the same stack frame) after calling forget on the <code>Pin&lt;&amp;mut Transfer&gt;</code></p>



<a name="211838616"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211838616" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211838616">(Sep 30 2020 at 21:53)</a>:</h4>
<p>Which gets us back to where we are now, asking for <code>StableDeref + 'static</code></p>



<a name="211838944"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211838944" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211838944">(Sep 30 2020 at 21:56)</a>:</h4>
<p>There is no guarantee that a thing like</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">struct</span> <span class="nc">Transfer</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">buf</span>: <span class="kp">&amp;</span><span class="o">'</span><span class="na">a</span> <span class="nc">mut</span><span class="w"> </span><span class="p">[</span><span class="kt">u8</span><span class="p">],</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>

<p>Will be dropped before anyone gets access to the buffer again, right ?</p>



<a name="211839424"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211839424" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211839424">(Sep 30 2020 at 22:01)</a>:</h4>
<p>Let me give a better example:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="p">{</span><span class="w"></span>
<span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">transfer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Transfer</span>::<span class="n">new</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">buf</span><span class="p">);</span><span class="w"></span>

<span class="n">pin_mut</span><span class="o">!</span><span class="p">(</span><span class="n">transfer</span><span class="p">);</span><span class="w"></span>
<span class="n">mem</span>::<span class="n">forget</span><span class="p">(</span><span class="n">transfer</span><span class="p">);</span><span class="w"></span>

<span class="c1">// transfer is Pin&lt;&amp;mut Transfer&gt;</span>
<span class="n">transfer</span><span class="p">.</span><span class="n">start</span><span class="p">();</span><span class="w"></span>

<span class="c1">// Drop of transfer not guaranteed here, if so, data race...</span>
<span class="n">buf</span><span class="p">[</span><span class="mi">10</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">10</span><span class="p">;</span><span class="w"></span>

<span class="c1">// Transfer guaranteed to run drop here</span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="211839597"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211839597" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211839597">(Sep 30 2020 at 22:03)</a>:</h4>
<p>I'm not sure I can fully follow your reasoning. Is the <code>Transfer</code> type a specific in-progress DMA operation?<br>
I wrote something similar in parallel:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="n">stack_buffer</span>:  <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="p">[</span><span class="kt">u8</span><span class="p">]</span><span class="w"></span>
<span class="c1">// DMABase keeps track of all onging DMA operations</span>
<span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">dma_base</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">DMABase</span>::<span class="n">new</span><span class="p">(</span><span class="n">settings</span><span class="p">,</span><span class="w"> </span><span class="n">stack_buffer</span><span class="p">);</span><span class="w"></span>
<span class="c1">//  Pin + guarantee that `dma_base` will not be leaked and always be dropped.</span>
<span class="kd">let</span><span class="w"> </span><span class="n">dma_base</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">DMAPin</span>::<span class="n">new_unchecked</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">dma_base</span><span class="p">)</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="211839709"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211839709" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211839709">(Sep 30 2020 at 22:04)</a>:</h4>
<p>The thing is the guarantee of <code>Pin</code> are not enough as it doesn't require <code>Transfer</code> to be dropped.<br>
(Through in the example above it will do so.)</p>



<a name="211839743"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211839743" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211839743">(Sep 30 2020 at 22:05)</a>:</h4>
<p>Yes, Transfer is what starts and manages a DMA peripheral and transfers</p>



<a name="211839797"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211839797" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211839797">(Sep 30 2020 at 22:05)</a>:</h4>
<p>But you have to follow the invariant of Pin which states that Drop must run if the thing gets deallocate (i.e. end of stack frame)</p>



<a name="211839809"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211839809" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211839809">(Sep 30 2020 at 22:06)</a>:</h4>
<p>Which pin_mut! complies with</p>



<a name="211839874"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211839874" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211839874">(Sep 30 2020 at 22:06)</a>:</h4>
<p>The problem is what if you example happens in a <code>async fn</code> ?</p>
<p>In which case you can no longer guarantee that drop is run.</p>
<p>E.g.</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">async</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">transfer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Transfer</span>::<span class="n">new</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">buf</span><span class="p">);</span><span class="w"></span>

<span class="w">    </span><span class="p">[</span><span class="o">..</span><span class="p">.]</span><span class="w"> </span><span class="c1">//pin transfer start it etc.</span>

<span class="w">    </span><span class="c1">// transfer can leak here</span>
<span class="w">    </span><span class="n">something</span><span class="p">.</span><span class="k">await</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="211839887"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211839887" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211839887">(Sep 30 2020 at 22:06)</a>:</h4>
<p>The problem is that the buffer can be used after the forget of the Pin&lt;&amp;mut Transfer&gt; buf before Transfer::drop</p>



<a name="211839951"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211839951" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211839951">(Sep 30 2020 at 22:07)</a>:</h4>
<p>Sorry, I edited the code, the transfer only starts after getting a Pin&lt;&amp;mut Transfer&gt; and calling start with it</p>



<a name="211840037"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211840037" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211840037">(Sep 30 2020 at 22:08)</a>:</h4>
<p>Yes, but once <code>await</code> is included transfer can always leak. (I edited the last block to make it more clear).</p>



<a name="211840147"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211840147" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211840147">(Sep 30 2020 at 22:09)</a>:</h4>
<p>Sorry, I haven't used async that much, how could that go around the Pin invariant ?</p>



<a name="211840216"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211840216" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211840216">(Sep 30 2020 at 22:10)</a>:</h4>
<p>If it's on the stack and it's pinned the drop should run by the end of the stack frame</p>



<a name="211840253"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211840253" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211840253">(Sep 30 2020 at 22:11)</a>:</h4>
<p>But like I said, this alone isn't enough for DMA, because we need a guarantee that the drop will run before the user has access to the buffer again</p>



<a name="211840272"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211840272" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211840272">(Sep 30 2020 at 22:11)</a>:</h4>
<p>Which we can only do with move semantics on the buffer</p>



<a name="211840439"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211840439" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211840439">(Sep 30 2020 at 22:14)</a>:</h4>
<blockquote>
<p>But like I said, this alone isn't enough for DMA, because we need a guarantee that the drop will run before the user has access to the buffer again</p>
</blockquote>
<p>We maybe could do this with some different <code>unsafe</code> constructor/ type like <code>struct DMAPin&lt;T&gt;(Pin&lt;T&gt;)</code> and instead of<br>
<code>pin_mut</code> have a macro which makes sure the buffer isn't available, maybe. </p>
<p><em>But the problem is in a async function you don't have the guarantee that the anything after the first await runs.</em></p>



<a name="211840503"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211840503" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211840503">(Sep 30 2020 at 22:14)</a>:</h4>
<p>Let me try to re-write my code above to be somewhat similar to what async maybe does (i.e. just conceptually similar).</p>



<a name="211840517"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211840517" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211840517">(Sep 30 2020 at 22:15)</a>:</h4>
<p>But we do have a guarantee that its place in memory will remain there unused, no ?</p>



<a name="211840548"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211840548" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211840548">(Sep 30 2020 at 22:15)</a>:</h4>
<p>No, give me a moment.</p>



<a name="211840774"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211840774" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211840774">(Sep 30 2020 at 22:17)</a>:</h4>
<blockquote>
<p>We maybe could do this with some different <code>unsafe</code> constructor/ type like <code>struct DMAPin&lt;T&gt;(Pin&lt;T&gt;)</code> and instead of <code>pin_mut</code> have a macro which makes sure the buffer isn't available, maybe. </p>
</blockquote>
<p>We would need to "move" the buffer in and give it back at the end of the transfer, which it's a bit cumbersome, we're doing this now btw, we use <code>StableDeref + 'static</code> for thath</p>



<a name="211841169"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211841169" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211841169">(Sep 30 2020 at 22:23)</a>:</h4>
<p>Like, that async block will be turned into a future thaf must be pinned before being able to run, right ? If it's pinned at least once then we get the invariant that drop will run before that memory gets used by something else, no ?</p>



<a name="211848773"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211848773" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211848773">(Sep 30 2020 at 22:35)</a>:</h4>
<p>[EDIT: deleted the futures async transformation pseudo code it turns out that it was well understood and the pseudo code just obfuscates the discussion]</p>
<p>The point is that the future  could be leaked between it being polled initially (and Transfer being created, pinned and started) and it being polled often enough to complete it and reach the End state.</p>
<p>With <code>?Leak</code> having a <code>?Leak</code> type in the future would make the future implicitly <code>?Leak</code>and as such you couldn't leak it anymore.</p>
<p>With the API we discussed we would need to make it unsafe to use it in a future/async block. But the whole point of this is to make it usable in a embedded focused async/await runtime.</p>



<a name="211849070"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211849070" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211849070">(Sep 30 2020 at 22:40)</a>:</h4>
<p>To complete the above example we could have:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="n">future</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">[</span><span class="o">..</span><span class="p">.]</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="n">pin_mut</span><span class="o">!</span><span class="p">(</span><span class="n">future</span><span class="p">);</span><span class="w"></span>
<span class="c1">// A special block_on on a already pinned future</span>
<span class="c1">// which randomly stops before completing the future</span>
<span class="n">block_on_with_random_failure</span><span class="p">(</span><span class="n">future</span><span class="p">)</span><span class="w"></span>
<span class="n">mem</span>::<span class="n">forget</span><span class="p">(</span><span class="n">future</span><span class="p">);</span><span class="w"> </span><span class="c1">//EDIT:  This doesn't work</span>
<span class="c1">// now dropping stack frame DMA is potentially still writing to</span>
</code></pre></div>



<a name="211849576"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211849576" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211849576">(Sep 30 2020 at 22:46)</a>:</h4>
<p>I'm logging out soon but two takaways from today:</p>
<ul>
<li>
<p><del>DMA + async/await + stack based buffers <em>required</em> <code>?Leak</code> I (<em>now</em>) see no sane way around it.</del><br>
   EDIT: No, it seems there is no way to safely leak a future on the stack???</p>
</li>
<li>
<p>The <code>Pin</code>'s unsafe-contract wrt. drop guarantees  abstraction doesn't work with anything pinned and we might need to review that. But it seems that without something like DMA  this can't safety hole isn't a problem.</p>
</li>
</ul>



<a name="211850010"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211850010" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211850010">(Sep 30 2020 at 22:53)</a>:</h4>
<hr>
<blockquote>
<p>Like, that async block will be turned into a future thaf must be pinned before being able to run, right ? If it's pinned at least once then we get the invariant that drop will run before that memory gets used by  something else, no ?</p>
</blockquote>
<p>If we take the description of the current unsafe-contract from std: Yes.</p>
<p><del>But if we do so <code>pin_mut!</code> is unsafe and any form of "pin something on the stack" is unsafe.</del><br>
EDIT: Or maybe not?</p>



<a name="211850346"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211850346" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211850346">(Sep 30 2020 at 22:58)</a>:</h4>
<p>pin mut shadows the original thing so you can't call forget on it, so it would be dropped on the end of the stack frame that it was created</p>



<a name="211850381"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211850381" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211850381">(Sep 30 2020 at 22:59)</a>:</h4>
<p>Yes I just realized that  myself.</p>



<a name="211850391"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211850391" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211850391">(Sep 30 2020 at 22:59)</a>:</h4>
<p>But again, it wouldn't be enough to DMA, because of the buffer</p>



<a name="211850514"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211850514" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211850514">(Sep 30 2020 at 22:59)</a>:</h4>
<p>It only gets dropped by the end of the stack frame, while you could re-use the buffer between mem::forget the transfer and the end of the stack frame</p>



<a name="211850605"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211850605" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211850605">(Sep 30 2020 at 23:00)</a>:</h4>
<p>So we would need to take "ownership" of the buffer</p>



<a name="211850618"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211850618" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211850618">(Sep 30 2020 at 23:00)</a>:</h4>
<p>It clearly is possible to leak heap allocated futures.</p>
<p>But is it possible that because of the interactions between async/Pin etc. it's not possible to leak stack allocated futures?</p>



<a name="211850685"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211850685" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211850685">(Sep 30 2020 at 23:01)</a>:</h4>
<p>The only way is if you have a divergent function, I think</p>



<a name="211850700"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211850700" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211850700">(Sep 30 2020 at 23:01)</a>:</h4>
<p>Otherwise you break Pin's invariant</p>



<a name="211850712"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211850712" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211850712">(Sep 30 2020 at 23:01)</a>:</h4>
<blockquote>
<p>So we would need to take "ownership" of the buffer</p>
</blockquote>
<p>With <code>alloca</code> something like a stack allocated owned <code>DMABuffer</code> instance should be possible. (But then <code>alloca</code> is unstable)</p>



<a name="211850774"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211850774" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211850774">(Sep 30 2020 at 23:02)</a>:</h4>
<p>What I actually use is <code>heapless::Box</code> it kinda works like a charm</p>



<a name="211850790"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211850790" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211850790">(Sep 30 2020 at 23:02)</a>:</h4>
<p>But it can be a bit wasteful on the resources</p>



<a name="211850822"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211850822" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211850822">(Sep 30 2020 at 23:03)</a>:</h4>
<p>It's a static allocated pool with fixed size allocations</p>



<a name="211850864"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211850864" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211850864">(Sep 30 2020 at 23:03)</a>:</h4>
<p>So that way I can pass it to the Transfer and get it back after and just do my work anywhere and drop it</p>



<a name="211850921"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211850921" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211850921">(Sep 30 2020 at 23:04)</a>:</h4>
<p>But yeah, no stack stuff</p>



<a name="211850946"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211850946" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211850946">(Sep 30 2020 at 23:04)</a>:</h4>
<p>With <code>!Leak</code> we could have that</p>



<a name="211851149"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211851149" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211851149">(Sep 30 2020 at 23:07)</a>:</h4>
<p>These are the traits we are using today to mark the buffer as safe for DMA APIs: <a href="https://docs.rs/embedded-dma/0.1.2/embedded_dma/">https://docs.rs/embedded-dma/0.1.2/embedded_dma/</a></p>



<a name="211851256"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211851256" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211851256">(Sep 30 2020 at 23:09)</a>:</h4>
<p>It's basically <code>StableDeref + 'static</code></p>



<a name="211851273"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211851273" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211851273">(Sep 30 2020 at 23:09)</a>:</h4>
<p>But with some changes to also work with MaybeUninit</p>



<a name="211851703"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211851703" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211851703">(Sep 30 2020 at 23:15)</a>:</h4>
<p>(Random thing: Is it just me or is <code>heapless::Box</code> missing a <code>Drop</code> implementation?)</p>



<a name="211851926"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211851926" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211851926">(Sep 30 2020 at 23:18)</a>:</h4>
<p>=&gt; Turns out there are two <code>Box</code> types one with and one without drop <span aria-label="laughter tears" class="emoji emoji-1f602" role="img" title="laughter tears">:laughter_tears:</span>  I need to go to bed.</p>



<a name="211852092"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/211852092" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#211852092">(Sep 30 2020 at 23:20)</a>:</h4>
<p>Heh, it's indeed a bit confusing the first time you look at it</p>



<a name="212086631"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212086631" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212086631">(Oct 02 2020 at 15:06)</a>:</h4>
<p>I have been playing around with a API.</p>
<p>Basically you will have something like:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="cp">#[macro_export]</span><span class="w"></span>
<span class="n">macro_rules</span><span class="o">!</span><span class="w"> </span><span class="n">ra_buffer_anchor</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="p">(</span><span class="cp">$name</span>:<span class="nc">ident</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="cp">$init</span>:<span class="nc">literal</span><span class="p">;</span><span class="w"> </span><span class="cp">$size</span>:<span class="nc">literal</span><span class="p">]</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">AccessType</span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">(</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="cp">$name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="cp">$init</span><span class="p">;</span><span class="w"> </span><span class="cp">$size</span><span class="p">];</span><span class="w"></span>
<span class="w">        </span><span class="c1">// Safe: By putting the anchor on the same stack scope as the buffer</span>
<span class="w">        </span><span class="c1">//       and by then pinning it in place and lastly shadowing the</span>
<span class="w">        </span><span class="c1">//       buffer and unpinned anchor preventing other access to them</span>
<span class="w">        </span><span class="c1">//       we can make sure that:</span>
<span class="w">        </span><span class="c1">//       1. the anchor isn't moved away / leaked</span>
<span class="w">        </span><span class="c1">//       2. no access to the buffer before anchor is dropped. (actually in this case the buffer can only be</span>
<span class="w">        </span><span class="c1">//            accessed through the anchor).</span>
<span class="w">        </span><span class="c1">//       3. anchor is dropped or the memory anchor is on is forever leaked</span>
<span class="w">        </span><span class="c1">//</span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="cp">$name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">RABufferAnchor</span>::<span class="n">new_unchecked</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="cp">$name</span><span class="p">)</span><span class="w"> </span><span class="p">};</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="cp">$name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">Pin</span>::<span class="n">new_unchecked</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="cp">$name</span><span class="p">)</span><span class="w"> </span><span class="p">};</span><span class="w"></span>
<span class="w">    </span><span class="p">);</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>

<p>Which you can use like following:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="n">ra_buffer_anchor</span><span class="o">!</span><span class="p">(</span><span class="n">buffer1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="k">u8</span><span class="p">;</span><span class="w"> </span><span class="mi">1024</span><span class="p">]</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">FakeDMA</span><span class="p">);</span><span class="w"></span>
<span class="c1">//buffer1: RABufferHandle&lt;'a, FakeDMA&gt;</span>
<span class="c1">// buffer1 can be passed around</span>
</code></pre></div>

<p>An the buffer you can use roughly like this:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">operation</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fake_dma</span>::<span class="n">start_copy</span><span class="p">(</span><span class="o">&amp;</span><span class="n">buffer1</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">buffer2</span><span class="p">).</span><span class="k">await</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="n">mem</span>::<span class="n">forget</span><span class="p">(</span><span class="n">operation</span><span class="p">)</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
<span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="c1">// this will await completion of previous leaked DMA operation before</span>
<span class="w">    </span><span class="c1">// starting a new one. (it will also hint to the previous operation to be</span>
<span class="w">    </span><span class="c1">// canceled).</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">operation</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fake_dma</span>::<span class="n">start_copy</span><span class="p">(</span><span class="o">&amp;</span><span class="n">buffer2</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">buffer1</span><span class="p">).</span><span class="k">await</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="n">operation</span><span class="p">.</span><span class="n">complete</span><span class="p">().</span><span class="k">await</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>

<p>Through the design isn't yet done.</p>
<p>Also I had another design where the dma operation consumed the <code>RABufferHandle</code>  and<br>
return it back once it completes, but I fare that would be really annoying to use.</p>



<a name="212166457"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212166457" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212166457">(Oct 03 2020 at 11:10)</a>:</h4>
<p><span class="user-mention silent" data-user-id="209646">Philipp Korber</span> <a href="#narrow/stream/122651-general/topic/Opt-in.20guaranteed.20destructors/near/211850618">said</a>:</p>
<blockquote>
<p>It clearly is possible to leak heap allocated futures.</p>
<p>But is it possible that because of the interactions between async/Pin etc. it's not possible to leak stack allocated futures?</p>
</blockquote>
<p>stack memory definitely gets deallocated when the function returns, so it must not be possible to leak anything that's stack-allocated an pinned unless the function diverges. everything else would violate the pinning contract.</p>



<a name="212166462"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212166462" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212166462">(Oct 03 2020 at 11:10)</a>:</h4>
<blockquote>
<p>Btw. I think I just realized that pinning any stack allocated future is technically braking the Pin unsafe-contract. It's just that because when we leak pin, drop the stack frame and reallocate the stack frame (defacto reusing memory) due to lifetimes we can't "poke" the leaked and not droped but mem-resued future anymore and as such can't exploit the contract breach. Uhm we might need to reformulate the unsafe-contract of Pin...</p>
</blockquote>
<p>could you elaborate? I don't understand how the contract is being violated here.</p>



<a name="212168555"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212168555" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212168555">(Oct 03 2020 at 12:06)</a>:</h4>
<p>Doesn’t Ralf’s point expand beyond this embedded/DMA case?￼</p>



<a name="212168580"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212168580" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212168580">(Oct 03 2020 at 12:07)</a>:</h4>
<blockquote>
<p>so it must not be possible to leak anything that's stack-allocated an pinned unless the function diverges. everything else would violate the pinning contract.</p>
</blockquote>



<a name="212180427"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212180427" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212180427">(Oct 03 2020 at 17:04)</a>:</h4>
<p>Yeah sure. This mostly shows that sound stack pinning is really hard as you have to ensure the destructor gets called, because you know that memory is deallocated. That's why it needs this shadowing trick.</p>



<a name="212182302"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212182302" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212182302">(Oct 03 2020 at 17:50)</a>:</h4>
<blockquote>
<p>That's why it needs this shadowing trick.</p>
</blockquote>
<p>But is the shadowing even enough? Can't you do something like:</p>
<ol>
<li>start a poll of a future</li>
<li>pin something on the "stack" (a.k.a. part of the generated enum)</li>
<li>start the "other" code that will write to the stack address </li>
<li>forget the pinned value</li>
<li>finish the poll with <code>Pending</code></li>
<li>poll the future again</li>
<li>create something else on the stack that uses the address again</li>
<li>the "other" actor finally writes to the stack space, and now it's unsafe</li>
</ol>



<a name="212182574"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212182574" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212182574">(Oct 03 2020 at 17:56)</a>:</h4>
<p>We ran into an issue with relying on shadowing a stack variable at some point, it was unsound in the presence of <code>yield</code>. In hindsight, maybe that isn't true, since generators are also <code>Pin</code>ned?</p>



<a name="212189471"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212189471" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212189471">(Oct 03 2020 at 20:55)</a>:</h4>
<blockquote>
<p>could you elaborate? I don't understand how the contract is being violated here.</p>
</blockquote>
<p>I was confused, it isn't as there is no safe way to leak a value pinned to the stack.</p>



<a name="212189625"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212189625" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212189625">(Oct 03 2020 at 20:58)</a>:</h4>
<blockquote>
<p>forget the pinned value</p>
</blockquote>
<p>You can not forget the pinned value safely.</p>
<p>If you use the standard way to pin things to the stack <code>pin_mut!()</code> it makes sure<br>
that you can't forget the pinned value by making sure it's owned and by shadowing it.<br>
Furthermore pinning only affects the value de-referenced directly but not anything<br>
de-referenced from the de-referenced value so a <code>Pin&lt;&amp;mut &amp;mut T&gt;</code> only pins<br>
the second <code>&amp;mut</code> but not the <code>T</code>. Which is important or else you could just use<br>
<code>ManuallyDrop</code> to "forget" the pinned value.</p>



<a name="212189806"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212189806" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212189806">(Oct 03 2020 at 21:03)</a>:</h4>
<p>It's likely that I'm missing something crucial, but I don't see why you can't do something of the general shape as this uncompiled/untested code:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">fn</span> <span class="nf">a</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">impl</span><span class="w"> </span><span class="n">Future</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">buf</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="mi">16</span><span class="p">];</span><span class="w"> </span><span class="c1">// pin this somehow</span>
<span class="w">    </span><span class="n">future</span>::<span class="n">poll_fn</span><span class="p">(</span><span class="o">|</span><span class="n">ctx</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">start_dma_transfer</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">buf</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="n">Poll</span>::<span class="n">Pending</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="p">})</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">b</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">impl</span><span class="w"> </span><span class="n">Future</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">future</span>::<span class="n">poll_fn</span><span class="p">(</span><span class="o">|</span><span class="n">ctx</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="p">();</span><span class="w"></span>
<span class="w">        </span><span class="n">a</span><span class="p">.</span><span class="n">poll</span><span class="p">(</span><span class="n">ctx</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="n">mem</span>::<span class="n">forget</span><span class="p">(</span><span class="n">a</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="n">Poll</span>::<span class="n">Pending</span><span class="w"></span>
<span class="w">    </span><span class="p">})</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="212189807"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212189807" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212189807">(Oct 03 2020 at 21:03)</a>:</h4>
<p>E.g. following is unsafe as it violates the pin contract:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">T</span>::<span class="n">new</span><span class="p">();</span><span class="w"></span>
<span class="c1">// breach of unsafe contract as you must make sure you don't forget x</span>
<span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">pinned</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">Pin</span>::<span class="n">new_unchecked</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="p">};</span><span class="w"></span>
<span class="nb">drop</span><span class="p">(</span><span class="n">pinned</span><span class="p">);</span><span class="w"></span>
<span class="n">mem</span>::<span class="n">forget</span><span class="p">(</span><span class="n">x</span><span class="p">);</span><span class="w"></span>
</code></pre></div>

<p>But following is safe:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">pinned</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">T</span>::<span class="n">new</span><span class="p">();</span><span class="w"></span>
<span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">pinned</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">Pin</span>::<span class="n">new_unchecked</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">pinned</span><span class="p">)</span><span class="w"> </span><span class="p">};</span><span class="w"></span>
<span class="c1">// can't forget the T in pinned due to shadowing</span>
<span class="p">[</span><span class="o">..</span><span class="n">arbitrary</span><span class="w"> </span><span class="n">safe</span><span class="w"> </span><span class="n">code</span><span class="o">..</span><span class="p">.]</span><span class="w"></span>
</code></pre></div>



<a name="212189847"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212189847" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212189847">(Oct 03 2020 at 21:04)</a>:</h4>
<p>Effectively, I'm trying to show that the forget happens "outside" the stack frame where the pin occurs.</p>



<a name="212189978"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212189978" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212189978">(Oct 03 2020 at 21:08)</a>:</h4>
<p>The problem is that  in that code:</p>
<ul>
<li><code>start_dma_transfer</code> must be <code>unsafe</code> as it must be guaranteed to last until dma is completed </li>
<li>
<p>you are stack allocating a buffer and passing that ref to a future, this won't work as the stack it's on<br>
   will be dropped once the future is returned. (it also won't compile thanks to the borrow checked)</p>
</li>
<li>
<p>to poll a future you need to pin it at which point you can not safely leak it anymore (without literally<br>
   leaking the stack memory)</p>
</li>
</ul>



<a name="212189999"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212189999" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212189999">(Oct 03 2020 at 21:08)</a>:</h4>
<hr>
<blockquote>
<p>Effectively, I'm trying to show that the forget happens "outside" the stack frame where the pin occurs.</p>
</blockquote>
<p>Which isn't possible if the future is polled on the stack with safe code.</p>



<a name="212190156"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212190156" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212190156">(Oct 03 2020 at 21:12)</a>:</h4>
<p>There are only two things which can happen with memory onto which you pinned something:</p>
<ul>
<li>You properly run drop on the thing which was pinned.</li>
<li>You leak that memory permanently.</li>
</ul>
<p>As you can't leak the stack permanently you must run drop.</p>
<p>And luckily the way <code>Pin</code> is designed there is no safe way to forget the stack pinned value (assuming you<br>
used <code>pin_mut!()</code>) without leaking the whole stack.</p>



<a name="212190162"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212190162" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212190162">(Oct 03 2020 at 21:12)</a>:</h4>
<blockquote>
<p>without literally leaking the stack memory</p>
</blockquote>
<p>This may be a part of where I'm getting stuck. I think this may not literally mean "stack". My brain says that it's not <em>possible</em> to leak stack memory. When a function exits, the stack pointer is popped and the next function call uses it.</p>



<a name="212190173"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212190173" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212190173">(Oct 03 2020 at 21:13)</a>:</h4>
<blockquote>
<p>it's not possible to leak stack memory. When a function exits, the stack pointer is popped and the next function call uses it.</p>
</blockquote>
<p>This is why it's so important that there is no safe way to not drop a stack pinned value.</p>



<a name="212190224"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212190224" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212190224">(Oct 03 2020 at 21:14)</a>:</h4>
<p>As a side note if you pin something to the "stack" in a async function it not necessarily the function stack in the classical sense.</p>



<a name="212190233"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212190233" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212190233">(Oct 03 2020 at 21:14)</a>:</h4>
<p>I'm afraid that you are restating the same points back at me multiple times without my understanding changing. This may not be a good use of your time. <span aria-label="smile" class="emoji emoji-1f642" role="img" title="smile">:smile:</span></p>



<a name="212190248"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212190248" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212190248">(Oct 03 2020 at 21:15)</a>:</h4>
<p>Due to the way async transforms things a pin to the "stack" in a async function  might be a bit of memory in the create future which might be moved onto the heap before being pinned/sheduled.</p>



<a name="212190368"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212190368" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212190368">(Oct 03 2020 at 21:18)</a>:</h4>
<p>So e.g. in following code:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="n">future</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">..</span><span class="p">.;</span><span class="w"></span>
<span class="w">    </span><span class="n">pin_mut</span><span class="o">!</span><span class="p">(</span><span class="n">foo</span><span class="p">);</span><span class="w"></span>
<span class="w">    </span><span class="o">....</span><span class="w"></span>
<span class="p">};</span><span class="w"></span>
<span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">fut</span><span class="w">  </span><span class="o">=</span><span class="w"> </span><span class="nb">Box</span>::<span class="n">pin</span><span class="p">(</span><span class="n">future</span><span class="p">);</span><span class="w"></span>
<span class="n">poll_boxed_future</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">fut</span><span class="p">);</span><span class="w"></span>
<span class="n">mem</span>::<span class="n">forget</span><span class="p">(</span><span class="n">fut</span><span class="p">);</span><span class="w"></span>
</code></pre></div>

<p>The "async stack"  foo is pinned  to is actually on the heap when polling the future and as such we can leak it permanently.</p>



<a name="212190461"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212190461" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212190461">(Oct 03 2020 at 21:21)</a>:</h4>
<p>To poll foo on the stack we would need to do:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="n">future</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">..</span><span class="p">.;</span><span class="w"></span>
<span class="w">    </span><span class="n">pin_mut</span><span class="o">!</span><span class="p">(</span><span class="n">foo</span><span class="p">);</span><span class="w"></span>
<span class="w">    </span><span class="o">....</span><span class="w"></span>
<span class="p">};</span><span class="w"></span>
<span class="n">pin_mut</span><span class="o">!</span><span class="p">(</span><span class="n">future</span><span class="p">);</span><span class="w"></span>
<span class="n">poll_pinned</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">future</span><span class="p">);</span><span class="w"></span>
</code></pre></div>

<p>In which case we shadow <code>future</code> and as such make sure it's dropped before the stack is potentially re-purposed.</p>
<p>Alternatively we could do:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="n">future</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">..</span><span class="p">.;</span><span class="w"></span>
<span class="w">    </span><span class="n">pin_mut</span><span class="o">!</span><span class="p">(</span><span class="n">foo</span><span class="p">);</span><span class="w"></span>
<span class="w">    </span><span class="o">....</span><span class="w"></span>
<span class="p">};</span><span class="w"></span>
<span class="c1">// in this unsafe-contract we guarantee not to "forget" future</span>
<span class="kd">let</span><span class="w"> </span><span class="n">pinned</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">Pin</span>::<span class="n">new_unchecked</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">future</span><span class="p">)</span><span class="w"> </span><span class="p">};</span><span class="w"></span>
<span class="n">poll_pinned</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">pinned</span><span class="p">);</span><span class="w"></span>
<span class="c1">// this would be a breach of the unsafe contract</span>
<span class="c1">// drop(pinned); mem::forget(future);</span>
</code></pre></div>



<a name="212190545"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212190545" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212190545">(Oct 03 2020 at 21:24)</a>:</h4>
<p>I am currently not aware of any async executor which does poll futures on the stack as this <br>
would have a lot of limitations.</p>
<p>E.g. all of <code>async-std</code>,<code>smol</code>,<code>tokio</code> do allocate memory on the heap and then move the future on the heap.</p>
<p>Through I could imagine some ways to do a stack only executor for some embedded use cases.</p>



<a name="212190843"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212190843" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212190843">(Oct 03 2020 at 21:32)</a>:</h4>
<hr>
<p>I created this library draft: <a href="https://github.com/rustonaut/remote-accessed-buffer">https://github.com/rustonaut/remote-accessed-buffer</a></p>
<p>Which will become a no_std, no alloc way to have a stack allocated buffer which you can use in  e.g. DMA.</p>
<p>Tomorrow I plane to add more documentation about the unsafe-contract and how it works this might<br>
be helpful for your understanding once it's done.</p>
<p>(Currently it's just a (working?) draft, no README, no proper doc about the unsafe contract, no integration test, no CI, etc.)</p>



<a name="212190981"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212190981" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212190981">(Oct 03 2020 at 21:36)</a>:</h4>
<p>Also the current design has some drawbacks:</p>
<ul>
<li>
<p>The way to interact with the buffer is through a <code>Pin&lt;&amp;mut ...&gt;</code> but they don't automatically reborrow<br>
   because of which they don't have the best UX</p>
</li>
<li>
<p>The fact that there are two lifetimes makes it a bit annoying to use.</p>
</li>
<li>
<p>Currently no good way for DMA (or similar) to get access to a <code>Waker</code> (I have a plan how to do it, but<br>
   it's not yet implemented)</p>
</li>
<li>
<p>No way to send the handle to the buffer to another thread (or Task) which is ok if the other target/source<br>
   of the DMA operation is some special address we supply by pointer. But means no good way to do DMA<br>
   between two of this buffers, fixing that is tricky without alloc <span aria-label="shrug" class="emoji emoji-1f937" role="img" title="shrug">:shrug:</span></p>
</li>
<li>
<p>Currently no existing DMA interface implementation (or similar) which uses this, I plan to add an example which uses a thread instead of DMA <span aria-label="stuck out tongue wink" class="emoji emoji-1f61c" role="img" title="stuck out tongue wink">:stuck_out_tongue_wink:</span></p>
</li>
</ul>



<a name="212215074"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212215074" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212215074">(Oct 04 2020 at 09:38)</a>:</h4>
<p><span class="user-mention" data-user-id="116155">@Jake Goulding</span> I think it would help if you tried to turn your non-compiling above into real code that compiles. I think you will find it does not work (without <code>unsafe</code>) and that should help explain why this is all safe.</p>
<p>Specifically, I think there is a problem with this part:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">fn</span> <span class="nf">b</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">impl</span><span class="w"> </span><span class="n">Future</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">future</span>::<span class="n">poll_fn</span><span class="p">(</span><span class="o">|</span><span class="n">ctx</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="p">();</span><span class="w"></span>
<span class="w">        </span><span class="n">a</span><span class="p">.</span><span class="n">poll</span><span class="p">(</span><span class="n">ctx</span><span class="p">);</span><span class="w"> </span><span class="c1">// &lt;!-- cannot do this without first pinning `a`</span>
<span class="w">        </span><span class="n">mem</span>::<span class="n">forget</span><span class="p">(</span><span class="n">a</span><span class="p">);</span><span class="w"> </span><span class="c1">// &lt;!-- cannot do this when `a` is pinned</span>
<span class="w">        </span><span class="n">Poll</span>::<span class="n">Pending</span><span class="w"></span>
<span class="w">    </span><span class="p">})</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="212215252"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212215252" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212215252">(Oct 04 2020 at 09:44)</a>:</h4>
<blockquote>
<p>My brain says that it's not possible to leak stack memory. When a function exits, the stack pointer is popped and the next function call uses it.</p>
</blockquote>
<p>I feel like you are confusing the proof obligations here. It is the responsibility of whoever creates a <code>Pin&lt;&amp;mut T&gt;</code> to prove that the memory this points to will not be deallocated without the destructor being called. If that memory is stack memory, it follows that you have to prove that the stack frame will not be popped without the destructor being called.</p>
<p>So to break this scheme you will have to find a way to create a pinned pointer to something on the stack, and then pop that stack frame without calling the destructor. That should be impossible and the general consensus seems to be that it indeed is impossible. However, this is tricky enough that we may indeed have missed some sneaky way to do that.</p>
<p>One particularly tricky case here is the case where the stack frame it points to is not a real stack frame but a generator (<code>async fn</code>), which I think is what your example does. In that case it must be the case that the <code>async fn</code> whose stack frame contains pinned data, is itself demanding pinning from its caller, i.e., it must not be <code>Unpin</code>. This way the "obligation to pin" is propagated outwards. I don't know enough about the <code>async fn</code> desugaring to tell if this is the case, but I sincerely hope so. :)</p>



<a name="212215370"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212215370" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212215370">(Oct 04 2020 at 09:46)</a>:</h4>
<p>Btw, there were some remarks made above that the <code>Pin</code> proof obligation is "non-local" in the sense that you have to promise something about future behavior. I think that however is mostly a matter of the framework you are using for reasoning. Sharing memory across multiple threads also has a "non-local" proof obligation because you must promise not to cause data races, and yet there are local ways to check this. I believe the same to be true for pinning -- with a sufficiently powerful logic, we can express these proof obligations in a local and modular way. In fact I believe the same underlying framework of <em>separation logic</em> that enables this for concurrency will also suffice for pinning.</p>



<a name="212219884"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212219884" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212219884">(Oct 04 2020 at 11:52)</a>:</h4>
<p><span class="user-mention" data-user-id="120791">@RalfJ</span>  At the risk of asking a PhD sized question, how would you actually model Pin? This has always looked a little shaky / tacked on to me, not least because it <em>was</em> tacked on, and I think there are still some open soundness problems IIRC, so I give decent odds that the concept doesn't actually survive formalization</p>



<a name="212221588"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212221588" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212221588">(Oct 04 2020 at 12:39)</a>:</h4>
<p><span class="user-mention silent" data-user-id="271719">Mario Carneiro</span> <a href="#narrow/stream/122651-general/topic/Opt-in.20guaranteed.20destructors/near/212219884">said</a>:</p>
<blockquote>
<p><span class="user-mention silent" data-user-id="120791">RalfJ</span>  At the risk of asking a PhD sized question, how would you actually model Pin? This has always looked a little shaky / tacked on to me, not least because it <em>was</em> tacked on, and I think there are still some open soundness problems IIRC, so I give decent odds that the concept doesn't actually survive formalization</p>
</blockquote>
<p>I'd say that's around 0.5 PhDs in size^^ I wrote some blog posts with rough ideas a while ago:</p>
<ul>
<li><a href="https://www.ralfj.de/blog/2018/04/05/a-formal-look-at-pinning.html">https://www.ralfj.de/blog/2018/04/05/a-formal-look-at-pinning.html</a></li>
<li><a href="https://www.ralfj.de/blog/2018/04/10/safe-intrusive-collections-with-pinning.html">https://www.ralfj.de/blog/2018/04/10/safe-intrusive-collections-with-pinning.html</a></li>
</ul>
<p>the actual formal details as I imagine them however require quite a bit of background... as in, much of part I and II of <a href="https://people.mpi-sws.org/~jung/phd/thesis-screen.pdf">my thesis</a> ;)<br>
We (mostly another PhD student and a former intern) have maybe around 80% of the formal work needed for this done; I still hope we can get back to it and complete that paper at some point.</p>



<a name="212232646"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212232646" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212232646">(Oct 04 2020 at 17:37)</a>:</h4>
<blockquote>
<p>I don't know enough about the <code>async fn</code> desugaring to tell if this is the case, but I sincerely hope so.</p>
</blockquote>
<p>The only way to abuse that would be by having a pinned <code>!Unpin</code> value survive an <code>.await</code> / <code>yield</code> point. But that automatically makes that field a member of the generator, (otherwise the value wouldn't exist when repolling). And given the way Rust types and auto-traits work, that automatically infects the generator with <code>Unpin</code> (no need  to know the exact unsugaring of the state machine, thus). So all is good <span aria-label="smile" class="emoji emoji-1f642" role="img" title="smile">:smile:</span> The worst thing that can happen is the generator being <em>overly restrictive</em> in that it may not be unpinned even "when it could" (same as <code>None::&lt;impl !Unpin&gt;</code> not being an unpinnable instance, <em>etc.</em>).</p>



<a name="212240636"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212240636" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212240636">(Oct 04 2020 at 20:37)</a>:</h4>
<blockquote>
<p>And given the way Rust types and auto-traits work, that automatically infects the generator with Unpin (no need to know the exact unsugaring of the state machine, thus).</p>
</blockquote>
<p>Yes that is how I hoped things work. :) Thanks for confirming.</p>



<a name="212375682"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212375682" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212375682">(Oct 06 2020 at 01:27)</a>:</h4>
<p><span class="user-mention" data-user-id="209646">@Philipp Korber</span> How would you prevent drop not being called on the DMA operation before popping the stack ?</p>
<p>I thought I had something, like, the operation being a future which borrows the buffer and on drop it stop the transfer, it was looking all nice, the borrow checker wouldn't let you use the buffer before the drop, even if you forgot the <code>Pin&lt;&amp;mut DMA&gt;</code>, but that would only work if the operation is on the stack</p>



<a name="212375735"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212375735" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212375735">(Oct 06 2020 at 01:28)</a>:</h4>
<p>If you use <code>Box::pin</code> instead and forget that pin, all bets are off, you can immediately re-use the buffer or pop the stack</p>



<a name="212375741"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212375741" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212375741">(Oct 06 2020 at 01:28)</a>:</h4>
<p>So I don't know how to do a safe interface with something like this</p>



<a name="212375816"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212375816" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212375816">(Oct 06 2020 at 01:30)</a>:</h4>
<p>I haven't found a way of doing this if the transfer doesn't own the buffer memory, i.e. buffer memory only gets invalidated together with the transfer</p>



<a name="212377066"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212377066" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212377066">(Oct 06 2020 at 01:58)</a>:</h4>
<p>Hmm, now I've looked at your code on github, it seems that in your case the buffer owns the transfer, right ? I think it might work, but it stumbles on the same inconvenience we have now with the transfer owning the buffer</p>



<a name="212377086"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212377086" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212377086">(Oct 06 2020 at 01:59)</a>:</h4>
<p>Which is a lot of consuming and giving it back, which can be troublesome when using interrupts because you need to place things in static variables, so or you need two Options or an enum in the form of <code>Left</code>/<code>Right</code></p>



<a name="212377162"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212377162" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212377162">(Oct 06 2020 at 02:00)</a>:</h4>
<p>And unfortunately in your case we would need the <code>Operation</code> back, since the DMA usually is a single resource modeled as a singleton</p>



<a name="212377690"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212377690" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212377690">(Oct 06 2020 at 02:12)</a>:</h4>
<p>Ah, but your macro has one advantage, using stack buffers, which was similar to my ideia with pinning the transfer, but I don't see a way right now of doing without a macro</p>



<a name="212418888"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212418888" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212418888">(Oct 06 2020 at 12:20)</a>:</h4>
<p><span class="user-mention silent" data-user-id="267734">Thales Fragoso</span> <a href="#narrow/stream/122651-general/topic/Opt-in.20guaranteed.20destructors/near/212375735">said</a>:</p>
<blockquote>
<p>If you use <code>Box::pin</code> instead and forget that pin, all bets are off, you can immediately re-use the buffer or pop the stack</p>
</blockquote>
<p>If you forget the result of <code>Box::pin</code> you would just have a memory leak. There is no way to safely re-use the heap allocation.</p>



<a name="212436286"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212436286" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212436286">(Oct 06 2020 at 14:33)</a>:</h4>
<p><span class="user-mention" data-user-id="133247">@bjorn3</span> The problem is when the type inside the <code>Pin&lt;Box&gt;</code> borrows a buffer on the stack, the compiler will let you re-use that buffer and pop that stack</p>



<a name="212436503"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212436503" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212436503">(Oct 06 2020 at 14:34)</a>:</h4>
<p>If you require the buffer itself to be pinned, then that can't happen. Eg only allow <code>Pin&lt;Box&lt;[u8]&gt;&gt;</code> and <code>Pin&lt;&amp;[u8]&gt;</code>.</p>



<a name="212436552"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212436552" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212436552">(Oct 06 2020 at 14:35)</a>:</h4>
<p>It doesn't make sense to allow <code>Pin&lt;Box&lt;&amp;[u8]&gt;&gt;</code>.</p>



<a name="212437882"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212437882" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212437882">(Oct 06 2020 at 14:43)</a>:</h4>
<p>Does pinning <code>[u8]</code> even achieve anything, irregardless of what pointer you use to refer to it?<br>
It doesn't have any Drop impl in the first place.</p>



<a name="212438043"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212438043" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212438043">(Oct 06 2020 at 14:44)</a>:</h4>
<p>Also it's <a href="https://doc.rust-lang.org/stable/std/marker/trait.Unpin.html#impl-Unpin-42">Unpin</a> so, no.</p>



<a name="212438167"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212438167" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212438167">(Oct 06 2020 at 14:45)</a>:</h4>
<p>Even with separate pinnings, I don't think we can do this without either the transfer owning the buffer type or the buffer type owning the transfer</p>



<a name="212438305"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212438305" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212438305">(Oct 06 2020 at 14:46)</a>:</h4>
<p>Even if you Pin the buffer or not, the stack will pop by the end of the scope together with the buffer, and if you put the transfer in a <code>Pin&lt;Box&gt;</code> and forget it you will have the same problem</p>



<a name="212438399"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212438399" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212438399">(Oct 06 2020 at 14:47)</a>:</h4>
<p>Or the buffer type needs to have a way to stop the transfer on Drop or the transfer has to own the buffer memory, so if you leak the transfer you also leak the buffer memory</p>



<a name="212438583"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212438583" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212438583">(Oct 06 2020 at 14:48)</a>:</h4>
<p>Either way you need a way to give or the buffer or the transfer back, the transfer manages singleton resources, so the user needs it back</p>



<a name="212446499"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212446499" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212446499">(Oct 06 2020 at 15:42)</a>:</h4>
<p>What about making the transfer itself <code>!Unpin</code> and requiring it to be pinned when starting it?</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">struct</span> <span class="nc">Transfer</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="c1">// ...</span>
<span class="w">    </span><span class="n">buf</span>: <span class="kp">&amp;</span><span class="o">'</span><span class="na">a</span> <span class="nc">mut</span><span class="w"> </span><span class="p">[</span><span class="kt">u8</span><span class="p">],</span><span class="w"></span>
<span class="w">    </span><span class="n">_unpin</span>: <span class="nc">PhantomUnpin</span><span class="p">,</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">impl</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="w"> </span><span class="n">Transfer</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">new</span><span class="p">(</span><span class="n">buf</span>: <span class="kp">&amp;</span><span class="o">'</span><span class="na">a</span> <span class="nc">mut</span><span class="w"> </span><span class="p">[</span><span class="kt">u8</span><span class="p">],</span><span class="w"> </span><span class="cm">/* ... */</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">Transfer</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">Transfer</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="c1">// ...</span>
<span class="w">            </span><span class="n">buf</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="n">_unpin</span>: <span class="nc">PhantomUnpin</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">start</span><span class="p">(</span><span class="bp">self</span>: <span class="nc">Pin</span><span class="o">&lt;&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">Self</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="c1">// start transfer if not already started or completed</span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">cancel</span><span class="p">(</span><span class="bp">self</span>: <span class="nc">Pin</span><span class="o">&lt;&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">Self</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="c1">// cancel transfer if started and not already completed</span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">impl</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="w"> </span><span class="nb">Drop</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">Transfer</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">drop</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="c1">// cancel transfer and wait until canceled or completed</span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="212451923"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212451923" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212451923">(Oct 06 2020 at 16:23)</a>:</h4>
<p>If you do</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="n">transfer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Box</span>::<span class="n">pin</span><span class="p">(</span><span class="n">transfer</span><span class="p">);</span><span class="w"></span>
<span class="n">transfer</span><span class="p">.</span><span class="n">start</span><span class="p">();</span><span class="w"></span>
<span class="n">mem</span>::<span class="n">forget</span><span class="p">(</span><span class="n">transfer</span><span class="p">);</span><span class="w"></span>
</code></pre></div>



<a name="212451992"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212451992" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212451992">(Oct 06 2020 at 16:23)</a>:</h4>
<p>You can then re-use the buffer passed to transfer as &amp;mut and pop its stack</p>



<a name="212452321"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212452321" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212452321">(Oct 06 2020 at 16:26)</a>:</h4>
<p>The thing that cancels the transfer in <code>Drop</code> must own the buffer, I think <em>then</em> having a <code>fn start(self: Pin&lt;&amp;mut Self&gt;)</code> would be sound (at least if I understood the earlier proposals correctly)</p>



<a name="212452507"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212452507" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212452507">(Oct 06 2020 at 16:27)</a>:</h4>
<p>It needs to be something like this:</p>
<div class="codehilite"><pre><span></span><code>struct Transfer {
    buffer: [u8],
}

impl Drop for Transfer {
    fn drop(&amp;mut self) { /* Wait for transfer to be complete, or abort */ }
}
</code></pre></div>



<a name="212452593"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212452593" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212452593">(Oct 06 2020 at 16:28)</a>:</h4>
<p>And the caller is somehow responsible for creating this pinned Dst.</p>



<a name="212452604"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212452604" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212452604">(Oct 06 2020 at 16:28)</a>:</h4>
<p>mhmm</p>



<a name="212452611"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212452611" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212452611">(Oct 06 2020 at 16:28)</a>:</h4>
<p>It might be possible to do this by unsizing coercion.</p>



<a name="212452622"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212452622" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212452622">(Oct 06 2020 at 16:28)</a>:</h4>
<p><code>&amp;'static mut [u8]</code></p>



<a name="212452642"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212452642" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212452642">(Oct 06 2020 at 16:28)</a>:</h4>
<p>I could see an API like <code>struct Transfer&lt;T: ?Sized + OwnedBuffer&gt;</code></p>



<a name="212452754"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212452754" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212452754">(Oct 06 2020 at 16:29)</a>:</h4>
<p>If we had <code>!Leak</code> then we probably could have borrowed buffers</p>



<a name="212455106"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212455106" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212455106">(Oct 06 2020 at 16:51)</a>:</h4>
<div class="codehilite"><pre><span></span><code>use std::marker::PhantomPinned;
use std::pin::Pin;

pub struct TransferBuf&lt;T: ?Sized&gt; {
    _unpin: PhantomPinned,
    buf: T,
}

pub struct Transfer {
    buffer: [u8],
}

impl&lt;T&gt; TransferBuf&lt;T&gt; {
    pub fn new(buf: T) -&gt; Self {
        TransferBuf { buf, _unpin: PhantomPinned }
    }
}

impl Transfer {
    pub fn new(pin: Pin&lt;&amp;mut TransferBuf&lt;[u8]&gt;&gt;) -&gt; Pin&lt;&amp;mut Self&gt; {
        unsafe {
            let ptr = &amp;mut *(Pin::into_inner_unchecked(pin)
                as *mut TransferBuf&lt;[u8]&gt; as *mut Self);
            Pin::new_unchecked(ptr)
        }
    }
}

fn main() {
    let mut buf = Box::pin(TransferBuf::new([0u8; 4]));
    Transfer::new(buf.as_mut());
}
</code></pre></div>



<a name="212455130"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212455130" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212455130">(Oct 06 2020 at 16:52)</a>:</h4>
<p>At least that makes it safe for the caller.</p>



<a name="212455281"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212455281" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> HeroicKatora <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212455281">(Oct 06 2020 at 16:53)</a>:</h4>
<p>This means you can't turn any buffer into a transfer buf, it specificially needs to be made one when allocating it.<br>
Stack allocation <code>pin_mut</code> would count but this is not optimal at all.</p>



<a name="212482061"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212482061" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212482061">(Oct 06 2020 at 20:34)</a>:</h4>
<blockquote>
<p>@Philipp Korber How would you prevent drop not being called on the DMA operation before popping the stack ?</p>
</blockquote>
<ul>
<li>
<p>The (not yet well documented, sorry) unsafe contract of the <code>RABufferAnchor::new_unchecked</code> constructor requires it to be directly pinned on the thread or async stack and that the buffer is on the same part of memory (for now let's just limit it to directly above the anchor on the (async or thread) stack.</p>
</li>
<li>
<p>The DAM operation (a handle to it or something similar)  is moved into the <code>RABufferAnchor</code> (which has a bit of stack space reserved for it).</p>
</li>
<li>
<p>Due to the guarantees of <code>Pin</code> and the unsafe contract we can make sure that <code>drop</code> is guaranteed to be called before the memory is re-purposed, even if it's normal stack memory (through it's mean to be pinned on the async stack).</p>
</li>
<li>
<p>In the <code>Drop</code> constructor we make sure to sync- block until the operation is completed, something similar to <code>AsyncDrop</code> could help make this more efficient.</p>
</li>
<li>
<p>You can directly await completion (or hint that it should be canceled) on the buffer handle (a <code>Pin&lt;&amp;mut RABufferAnchor&lt;...&gt;&gt;</code>).</p>
</li>
<li>
<p>The returned <code>OperationHandle</code> can also be used to await cancelation, but you don't need to. The fact that it resolves to a new <code>Pin&lt;&amp;mut RABufferAnchor&lt;...&gt;&gt;</code> is just utility, it also could resolve to <code>()</code> and this would not change much.</p>
</li>
<li>
<p>Before starting any new operation you must wait the end of the previous operation (a Noop if it already ended, there was none)</p>
</li>
<li>
<p>While <code>Pin&lt;&amp;mut ...&gt;</code> doesn't automatically re-borrow you can manually re-borrow by using <code>.as_mut()</code>. With that you can mostly threat the <code>Pin&lt;&amp;mut RABufferAnchor&gt;</code> like a <code>&amp;mut</code> ref to the buffer.</p>
</li>
<li>
<p>The handle to the operation which is stored in the anchore is as much pinned as the anchor and whatever writes/reads to/from the buffer can also write/read to/from it (but you must use some appropriate type of Cell). This allows handling <code>Waiter</code>'s  and similar.<br>
(and the API needs some improvements around that).</p>
</li>
</ul>
<blockquote>
<p>If you use Box::pin instead and forget that pin, all bets are off, you can immediately re-use the buffer or pop the stack</p>
</blockquote>
<p>The unsafe contract requires stack pinning. So this is not a problem.</p>
<blockquote>
<p>Which is a lot of consuming and giving it back, which can be troublesome when using interrupts because you need to place things in static variables, so or you need two Options or an enum in the form of Left/Right</p>
</blockquote>
<p>It doesn't really consume the handle, or more specifically you can re-borrow it. Once I implement <code>async fn buffer_ref(...) -&gt; &amp;[V]</code> and <code>async fn buffer_mut(...) -&gt; &amp;mut [V]</code>.  You should be able to do something like:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="n">ra_buffer_anchor</span><span class="o">!</span><span class="p">(</span><span class="n">buffer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="k">u8</span><span class="p">;</span><span class="w"> </span><span class="mi">1024</span><span class="p">]</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">DMAInteraction</span><span class="p">);</span><span class="w"></span>
<span class="k">while</span><span class="w"> </span><span class="n">foobar</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="c1">// start the dma, we here don't use the `OperationHandle` at all</span>
<span class="w">   </span><span class="n">dma</span>::<span class="n">start_data_to_buffer_copy</span><span class="p">(</span><span class="n">buffer</span><span class="p">.</span><span class="n">as_mut</span><span class="p">(),</span><span class="w"> </span><span class="o">..</span><span class="p">.</span><span class="n">source</span><span class="w"> </span><span class="n">etc</span><span class="p">.).</span><span class="k">await</span><span class="p">;</span><span class="w"></span>
<span class="w">   </span><span class="p">[</span><span class="o">..</span><span class="p">.</span><span class="kr">do</span><span class="w"> </span><span class="n">stuff</span><span class="o">..</span><span class="p">.]</span><span class="w"></span>
<span class="w">   </span><span class="c1">// buffer_mut makes sure to wait for any ongoing DMA operation to complete before</span>
<span class="w">   </span><span class="c1">// allowing access, lifetimes make sure you can't start a new DMA operation while the buffer</span>
<span class="w">   </span><span class="c1">// is borrowed.</span>
<span class="w">   </span><span class="n">modify_data_in_buffer</span><span class="p">(</span><span class="n">buffer</span><span class="p">.</span><span class="n">as_mut</span><span class="p">().</span><span class="n">buffer_mut</span><span class="p">().</span><span class="k">await</span><span class="p">)</span><span class="w"></span>
<span class="w">   </span><span class="n">dma</span>::<span class="n">start_data_from_buffer_copy</span><span class="p">(</span><span class="n">buffer</span><span class="p">.</span><span class="n">as_mut</span><span class="p">(),</span><span class="w"> </span><span class="o">..</span><span class="p">.</span><span class="n">source</span><span class="w"> </span><span class="n">etc</span><span class="p">.).</span><span class="k">await</span><span class="p">;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>

<blockquote>
<p>And unfortunately in your case we would need the Operation back, since the DMA usually is a single resource modeled as a singleton.</p>
</blockquote>
<p>Even with <code>Leak</code> you might need to adapt whatever you use to the DMA instructions, likely to a more low level DMA API. I'm completly sure that this can be done without any to big problems. But I don't know the exact underlying DMA API you  want to use.  I could loo into it if you link me some library or similar.</p>
<blockquote>
<p>but I don't see a way right now of doing without a macro</p>
</blockquote>
<p>Neither do I, at least without unsafe code.</p>
<blockquote>
<p>It doesn't make sense to allow <code>Pin&lt;Box&lt;&amp;[u8]&gt;&gt;.</code></p>
</blockquote>
<p>In my library the ownership of the buffer is semantically moved to the thing which does the DMA (or similar) operation.</p>
<p>My design is similar to a <code>Pin&lt;&amp;mut Wrapper&lt;&amp;mut [u8]&gt;&gt;&gt;</code> except that  due to the unsafe constructor of <code>Wrapper</code> (or to be precise <code>RABufferAnchor</code> the right guarantees are expanded to the underlying buffer.  It's also not a problem as it doesn't implement <code>Deref</code> and has some requirements about what buffer can be passed in. For some time I considered only allowing the<br>
buffer to be directly passed in e.g. <code>::new_unchecked([0u8; 1024])</code> but this is overly restrictive given that we already have unsafety in the constructor and have a macro to safly abstract it away which works similar to <code>pin_mut!</code>.</p>



<a name="212482995"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212482995" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212482995">(Oct 06 2020 at 20:42)</a>:</h4>
<blockquote>
<p>I could see an API like <code>struct Transfer&lt;T: ?Sized + OwnedBuffer&gt;</code></p>
</blockquote>
<p>The thing is owning the buffer is not enough you need certain guarantees about the memory. On the otherhand with stack pinning a anchor which has a mutable reference to the buffer and a unsafe guarantee that the buffer "lies" on the same part of the stack you have everything you need without needing taking permanent ownership of the buffer and while making it work with VLA (even in their <em>very</em> restricted form we have in the current RFC around them).</p>
<p>In the end I will use a macro to safely abstract over the "anchor needs stack binning" aspect anyway and if we have this anyway we can also extend to to handle the buffer creation so that we have a fully safe abstraction covering most use-cases.</p>
<p>Furthermore you normally don't need to ever move the buffer out of the anchor as the anchor allows access via <code>&amp;mut [V]</code>,<code>&amp;[V]</code> as long as no operation is ongoing.</p>



<a name="212487434"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212487434" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212487434">(Oct 06 2020 at 21:20)</a>:</h4>
<blockquote>
<p>.as_mut() re-borrows</p>
</blockquote>
<p>I would really love if we could have some way to add automatic re-borrow behaviour at least for method calls to anything semantically wrapping a <code>&amp;mut T</code>...</p>



<a name="212495504"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212495504" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212495504">(Oct 06 2020 at 22:47)</a>:</h4>
<blockquote>
<p>Either way you need a way to give or the buffer or the transfer back, the transfer manages singleton resources, so the user needs it back</p>
</blockquote>
<p>Looking at the DMA API in <code>stm32g0xx_hal</code> you probably mean the DMA channels.</p>
<p>I have a few ideas how this could be done. </p>
<p>All are based on the idea to "automatically place back the channel into some kind of slot" once the work is done.</p>
<p>The simplest one is to simple pass a <code>&amp;'long mut</code> reference of the channel to whatever starts the operation. Which should work as long as <code>'long</code> out-lifes the stack allocated buffer. I intentionally made sure that the operation handle which is lifted into the anchor does <em>not</em> need to be static. (It's also pinned and is only dropped after the operation completes so it allows some crazy stuff).</p>
<p>I will also change <code>OperationHandle.completion().await</code> to no longer return the wrapped <code>Pin&lt;&amp;mut RABufferAnchor&lt;..&gt;&gt;</code> instead it will return a item defined by the operation, e.g. a hint weather or not the operation completed or failed to complete. </p>
<p>There are also some open questions about how to best to task waking. Like can you call <code>waker.wake()</code> from a interrupt handler?  Probably not a good idea right as lock and cas-loops don't work well in interrupt handlers as far as I know?</p>
<p>Well luckily for me handling <code>Waker</code> is part of the glue-code (the implementer of the <code>OperationInteraction</code> trait) still I should make sure to provided utilities to make writing this glue code easy.</p>



<a name="212516832"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212516832" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212516832">(Oct 07 2020 at 05:31)</a>:</h4>
<blockquote>
<p>Probably not a good idea right as lock and cas-loops don't work well in interrupt handlers as far as I know ?</p>
</blockquote>
<p><span class="user-mention" data-user-id="209646">@Philipp Korber</span>  It's kinda of okay, if you choose your interrupt priorities carefully. The lock would be to (dynamically) increase the interrupt priority to the highest priority using the locked resource, CAS should also be okay, if your target supports it (most do).</p>
<p>It's more like a design thing, today we have like a bunch of interrupts priorities, usually more than you could ask for.</p>



<a name="212606922"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212606922" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212606922">(Oct 07 2020 at 19:22)</a>:</h4>
<p>Thanks, good to know.</p>



<a name="212628773"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212628773" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212628773">(Oct 07 2020 at 22:47)</a>:</h4>
<p>For bare-metal on a single core target, I should add. On other cases it's usually a per case thing.</p>



<a name="212632794"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212632794" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212632794">(Oct 07 2020 at 23:37)</a>:</h4>
<p>Given that you will anyway need some glue code between the buffer and a DMA API this should be fine.</p>
<p>So far it looks good, I will next emulate a  fake <code>DMA</code> API (using a thread <span aria-label="wink" class="emoji emoji-1f609" role="img" title="wink">:wink:</span>) similar to the one in <code>stm32g0xx_hal</code> to see how to best handle resource singletons.</p>



<a name="212639280"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212639280" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212639280">(Oct 08 2020 at 01:32)</a>:</h4>
<p><span class="user-mention" data-user-id="209646">@Philipp Korber</span> I just had a quick look at the one on g0, it seems to not have a transfer type yet. The one on the f4xx-hal is using our new crate for buffer traits, but the DMA on the F4 has a lot of whistles, so the code is a bit bigger</p>



<a name="212639304"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212639304" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212639304">(Oct 08 2020 at 01:33)</a>:</h4>
<p>The most interesting part would be the Transfer type by the end of the file (on the F4 HAL)</p>



<a name="212640738"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212640738" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212640738">(Oct 08 2020 at 02:03)</a>:</h4>
<p>I have to think about this a bit more.</p>
<p>But one think I was wondering about is: Given that we can have a <code>&amp;mut</code> to the <code>Transfer</code> while another thread (the DMA controller) writes to the buffer don't we need to store the buffer as <code>Option&lt;Cell&lt;BUF&gt;&gt;</code> due to aliasing rules?</p>
<p>I guess for a <code>Vec&lt;&gt;</code> that would not be a problem due to the additional pointer indirection, but for a <code>&amp;mut [Word]</code> it might be??</p>



<a name="212832590"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212832590" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212832590">(Oct 09 2020 at 14:26)</a>:</h4>
<p><span class="user-mention" data-user-id="209646">@Philipp Korber</span> hmm, not sure. We use compiler fences and pointer escapes to avoid certain problems with optimizations, I think it's kinda modeled as a FFI</p>



<a name="212912681"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212912681" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212912681">(Oct 10 2020 at 11:55)</a>:</h4>
<p><span class="user-mention silent" data-user-id="267734">Thales Fragoso</span> <a href="#narrow/stream/122651-general/topic/Opt-in.20guaranteed.20destructors/near/212375682">said</a>:</p>
<blockquote>
<p><span class="user-mention silent" data-user-id="209646">Philipp Korber</span> How would you prevent drop not being called on the DMA operation before popping the stack ?</p>
<p>I thought I had something, like, the operation being a future which borrows the buffer and on drop it stop the transfer, it was looking all nice, the borrow checker wouldn't let you use the buffer before the drop, even if you forgot the <code>Pin&lt;&amp;mut DMA&gt;</code>, but that would only work if the operation is on the stack</p>
</blockquote>
<p>all of this reminds me a lot of the discussions around io_uring, and there IIRC <span class="user-mention" data-user-id="256759">@boats</span> concluded that pinning doesn't help. their ringbahn crate might thus be a good source of inspiration?</p>



<a name="212913351"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212913351" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Diggsey <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212913351">(Oct 10 2020 at 12:16)</a>:</h4>
<p>This is a long thread! If I was to implement an API like this, I would be implementing an executor: the executor itself would have a blocking API that would borrow a list of stack-allocated buffers as input, and would be able to ensure that all DMA operations are terminated before returning.</p>
<p>The executor would be used something like this:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="n">dma_executor</span><span class="p">.</span><span class="n">run</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">buffers</span><span class="p">,</span><span class="w"> </span><span class="o">|</span><span class="n">spawner</span><span class="o">|</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="k">move</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">spawner</span><span class="p">.</span><span class="n">spwan</span><span class="p">(</span><span class="n">some_background_task</span><span class="p">());</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">spawner</span><span class="p">.</span><span class="n">spwan</span><span class="p">(</span><span class="n">some_dma_task</span><span class="p">());</span><span class="w"></span>
<span class="w">    </span><span class="n">a</span><span class="p">.</span><span class="k">await</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="n">b</span><span class="p">.</span><span class="k">await</span><span class="p">;</span><span class="w"></span>
<span class="p">});</span><span class="w"></span>
</code></pre></div>

<p>The reason you are having such difficulty defining a safe API is that you seem to want the stack buffers to be allocated without outliving the  executor, and I don't think that's possible: the buffers must necessarily outlive the executor, because the stack will be unwound up to the executor's stack frame each time a future yields.</p>



<a name="212915452"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212915452" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> boats <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212915452">(Oct 10 2020 at 13:13)</a>:</h4>
<p><span class="user-mention silent" data-user-id="211727">Jonas Schievink</span> <a href="#narrow/stream/122651-general/topic/Opt-in.20guaranteed.20destructors/near/211547758">said</a>:</p>
<blockquote>
<p>On embedded systems, doing the same thing as ringbahn does (heap-allocating an owned backing buffer) would, as far as I understand, result in <em>doubling</em> memory usage of DMA buffers, which is not an acceptable trade-off there. The alternative would be to make almost every DMA API <code>unsafe</code>, which is also not appealing, and with async/await, that would be the <em>only</em> API, so that wouldn't be very good.</p>
</blockquote>
<p>There doesn't seem to be much investigation of this assertion in this thread. Why can't you have an owned representation of the buffer without doubling memory usage? I don't know anything about DMA, but it seems suspect to me.</p>



<a name="212915650"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212915650" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> boats <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212915650">(Oct 10 2020 at 13:18)</a>:</h4>
<p>It doesn't <em>need</em> to be a heap allocated buffer - it just needs to be a type that represents the only safe way to read/write to that memory again</p>



<a name="212922074"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212922074" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212922074">(Oct 10 2020 at 16:01)</a>:</h4>
<blockquote>
<p>all of this reminds me a lot of the discussions around io_uring, and there IIRC @boats concluded that pinning doesn't help. their ringbahn crate might thus be a good source of inspiration?</p>
</blockquote>
<p>I'm pretty sure the think I'm <em>playing</em> around with here <a href="https://github.com/rustonaut/remote-accessed-buffer">https://github.com/rustonaut/remote-accessed-buffer</a> actually does work and is sound with stack pinned buffers. (Note as it's just a playground for me there is currently no Readme/CI etc.)</p>
<p>Through there are some <em>major</em> ergonomic drawbacks to it which for thinks like io-uring probably make no sense at all. Mainly it might hang (either async or even sync depending on the context) until the operation completes, which  with e.g. a bad implementation might be forever <span aria-label="shrug" class="emoji emoji-1f937" role="img" title="shrug">:shrug:</span> So I think as long as you can just use heap allocations going with "temporary leaking buffers while they are in use for completion based I/O" is the better solution (which is I think was ringbahn does).</p>
<p>But on embedded devices you might not have a heap.</p>
<p>You can have a static buffer, or a static pool you allocate buffers on. </p>
<p>The problem the static buffer will always be around which is really a problem for a low-memory situation where you for some time need a big buffer (or many buffers) but most times don't.</p>
<p>Furthermore leaking a <code>static</code> buffer on a low-memory environment is also a big problem (I guess, tbh. I'm not that experienced with embedded programming).</p>
<p>For me this is mainly a fun challenge, but I believe it might produce something use-full for the <code>no_std</code>, no <code>alloc</code> lowish-memory use-case.</p>



<a name="212922146"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212922146" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212922146">(Oct 10 2020 at 16:03)</a>:</h4>
<p>(There also might be some problems with big writable static buffers and application images on some embedded targets , but I don't know anything about this so just widely spukualting that maybe that could be a thing.)</p>



<a name="212922517"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212922517" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212922517">(Oct 10 2020 at 16:12)</a>:</h4>
<p><span class="user-mention" data-user-id="267734">@Thales Fragoso</span> : With the current design of dma in stm32f4xx-hal you will have to pass in a <code>'static</code> memory based buffer (heap or static). The reason for this is the <code>'static</code> lifetime bound on <code>BUFF</code>.  This could probably be fixed in many ways, including moving the <code>'static</code> bound from the type to the <code>init</code> method and provide <code>unsafe fn init_non_static(...)</code> function (and then there would be glue code for the specific non static buffer type abstracting away that unsafe). (just random ideas)</p>
<p>I also had some other ideas about alternate ways to do the <code>embedded_dma::Read/WriteBuffer</code> type in ways which works well for both <code>'static</code> leak based DMA buffers and other buffers. But I will first need try out how they work.</p>
<p>One think I'm wondering is how is the interrupt handling done, is the <code>Transfer</code> moved to the interrupt or is it handle in ways where the normal code might wait on the interrupt and then call <code>free</code>/<code>next_transfer</code>?</p>



<a name="212922522"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212922522" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212922522">(Oct 10 2020 at 16:12)</a>:</h4>
<p><a href="https://github.com/rustonaut/remote-accessed-buffer/blob/ca4033b1ae4ac5c02900935c11a6a0b36e103b78/src/lib.rs#L180">https://github.com/rustonaut/remote-accessed-buffer/blob/ca4033b1ae4ac5c02900935c11a6a0b36e103b78/src/lib.rs#L180</a></p>
<p>*upstream</p>



<a name="212922796"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212922796" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212922796">(Oct 10 2020 at 16:18)</a>:</h4>
<p><span class="user-mention" data-user-id="209646">@Philipp Korber</span> the <code>Transfer</code> is usually moved to a static.</p>
<p>About the 'static thing, we recently included an unsafe <code>StaticWriteBuffer</code> trait to embedded-dma, it's implemented for <code>WriteBuffer + 'static</code> but people can (unsafely) implement it for any type, we should change Transfer to use that</p>



<a name="212922807"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212922807" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212922807">(Oct 10 2020 at 16:19)</a>:</h4>
<p>But it might not work well with your design</p>



<a name="212922889"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212922889" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212922889">(Oct 10 2020 at 16:20)</a>:</h4>
<p>The transfer being on a static gives that ergonomic problem I was talking about when you need to consume resources, since you can't just consume a static, you need Option, etc</p>



<a name="212922905"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212922905" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212922905">(Oct 10 2020 at 16:21)</a>:</h4>
<blockquote>
<p>But it might not work well with your design</p>
</blockquote>
<p>Yes, the underlying buffer is still <code>'static</code>. And we can't have a <code>'static</code> handle/ref/pointer to a stack allocated buffer.</p>



<a name="212922956"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212922956" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212922956">(Oct 10 2020 at 16:22)</a>:</h4>
<p>Like I said, you can unsafely implement the new trait to whatever type you have, but not sure if it would be possible to combine with your work and still create a safe api on top</p>



<a name="212922966"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212922966" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212922966">(Oct 10 2020 at 16:22)</a>:</h4>
<p>Maybe if you implement it for <code>Pin&lt;...&gt;</code></p>



<a name="212922982"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212922982" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212922982">(Oct 10 2020 at 16:22)</a>:</h4>
<p>The new <code>StaticWriteBuffer</code></p>



<a name="212923063"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212923063" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212923063">(Oct 10 2020 at 16:24)</a>:</h4>
<p>Implementing it doesn't  really work as it would always break the unsafe contract of the <code>StaticWriteBuffer</code>, so this would not be sound on a library level, through I guess it could work by not ever exposing the <code>Transfer</code> type (so I would implement it for something like <code>struct UnsafeHanlde(Pin&lt;&amp;mu...&gt;)</code>).</p>



<a name="212923146"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212923146" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212923146">(Oct 10 2020 at 16:26)</a>:</h4>
<p>Hmm, yeah, those traits probably don't cover all use cases</p>



<a name="212923159"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212923159" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212923159">(Oct 10 2020 at 16:27)</a>:</h4>
<p>Through if I do that I probably would just implement <code>BufferRead</code> unsafely for a <code>Pin&lt;*mut ..&gt;</code> I think.  </p>
<p>Using <code>Read/WriteBuffer</code> is I think better for <code>Transfer</code> as the guarantees for <code>StaticRead/WriteBuffer</code> are stronger then what <code>Transfer</code> needs.</p>



<a name="212923292"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212923292" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212923292">(Oct 10 2020 at 16:30)</a>:</h4>
<p>One possibility would be to slightly extend the <code>unsafe</code> contract of <code>Read/WriteBuffer</code>. Basically just add a "if this is implemented for a non 'static type that type must make sure that the memory isn't re-purposed until it is sure that the DMA operation completes".</p>
<p>And then <code>Transfer</code> could remove the <code>'static</code> bound. </p>
<p>But then a non-static <code>Transfer</code> seems to be generally incompatible with how it's used wrt. interrupts.</p>



<a name="212923294"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212923294" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212923294">(Oct 10 2020 at 16:30)</a>:</h4>
<p>I decided to create them because a lot of people (including me once) were forgetting the <code>+ 'static</code> bound</p>



<a name="212923302"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212923302" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thales Fragoso <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212923302">(Oct 10 2020 at 16:30)</a>:</h4>
<p>Also, it gives an escape hatch to anyone that just wants to do things unsafely in their end application</p>



<a name="212923320"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Opt-in%20guaranteed%20destructors/near/212923320" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Philipp Korber <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Opt-in.20guaranteed.20destructors.html#212923320">(Oct 10 2020 at 16:31)</a>:</h4>
<p>Makes sense, that seems like something very easy to mess up wrt. unsafe code/ptr handling.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>